接上篇《12、索引库删除判断以及文档增删改查》
上一篇我们讲解了如何判断索引库是否存在并删除它,以及如何对索引库中的文档进行增删改查操作。本篇我们进入ElasticSearch的DSL语法的详解。
Elasticsearch(ES)作为强大的分布式搜索引擎,其核心功能之一是通过DSL(Domain Specific Language)实现灵活的数据查询。本文将深入解析ES DSL查询的三大核心分类:全文检索查询、精确查询和地理查询,结合实际场景和语法示例,帮助开发者快速掌握ES查询精髓。
一、DSL查询基础结构
ES查询的基本结构遵循JSON格式,主要包含以下两部分:
javascript
GET /indexName/_search
{
"query": {
// 查询条件定义
"查询类型":{
"查询条件":"条件值"
}
},
"from": 0, // 分页起始位置
"size": 10, // 每页返回数量
"sort": [ // 排序规则
{"price": "asc"}
]
}
二、全文检索查询
1. 使用场景
●博客文章内容搜索
●电商商品描述匹配
●日志分析中的文本挖掘
●任何需要基于文本相似度匹配的场景
2. 核心查询类型
(1)match查询(最常用)
javascript
GET /indexName/_search
{
"query": {
"match": {
"title": {
"query": "Elasticsearch教程",
"operator": "and", // 可选:and/or
"minimum_should_match": "75%", // 最小匹配度
"fuzziness": "AUTO" // 模糊匹配
}
}
}
}
关键参数:
●operator:控制多个查询词的逻辑关系(默认OR)
●minimum_should_match:设置最低匹配词比例
●fuzziness:允许的拼写错误容忍度(AUTO/0/1/2)
案例测试1:
javascript
# 模糊搜索
GET /hotel/_search
{
"query": {
"match": {
"all": "外滩如家"
}
}
}
案例结果1:
案例测试2:
javascript
# 模糊搜索
GET /hotel/_search
{
"query": {
"match": {
"name": {
"query": "7天酒店",
"operator": "and",
"minimum_should_match": "75%",
"fuzziness": "AUTO"
}
}
}
}
案例结果2:
(2)multi_match查询(多字段匹配)
javascript
GET /indexName/_search
{
"query": {
"multi_match": {
"query": "大数据分析",
"fields": ["title^3", "content", "tags"], // ^3表示权重
"type": "best_fields" // 匹配策略
}
}
}
匹配策略:
●best_fields:最佳字段匹配(默认)
●most_fields:多数字段匹配
●cross_fields:跨字段匹配
●phrase:短语匹配
●phrase_prefix:短语前缀匹配
案例测试:
javascript
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["brand^3", "name", "business"],
"type": "best_fields"
}
}
}
案例结果:
(3)match_phrase查询(短语匹配)
javascript
GET /indexName/_search
{
"query": {
"match_phrase": {
"content": "快速排序算法",
"slop": 1 // 允许词间最大距离
}
}
}
match_phrase查询用于精确匹配短语,同时允许指定词间最大距离(通过 slop 参数)
slop表示允许的词序调整次数(例如将"上海 浦东 东站"调整为"上海浦东 东站"需要1次调整)
案例测试:
javascript
GET /hotel/_search
{
"query": {
"match_phrase": {
"name": "上海浦东东站"
}
}
}
案例结果:
(4)query_string查询(复杂查询)
javascript
GET /indexName/_search
{
"query": {
"query_string": {
"query": "(Java OR Python) AND 开发",
"default_field": "content",
"fields": ["title^2", "content"]
}
}
}
特点:
支持Lucene查询语法
可指定多个字段及权重
适合复杂查询需求
案例测试1:
javascript
GET /hotel/_search
{
"query": {
"query_string": {
"query": "西藏 AND 万怡",
"default_field": "name"
}
}
}
案例结果1:
案例测试2:
javascript
GET /hotel/_search
{
"query": {
"query_string": {
"query": "(机场 OR 地铁) AND 如家",
"fields": ["name", "business"]
}
}
}
案例结果2:
注意:query_string查询默认会对文本进行分词处理,如果name字段被映射为keyword类型而不是text类型,查询可能不会按预期工作。例如"商业区"可能被分词为"商"、"业"和"区"三个词,查询要求同时包含这三个词,但很多"商业区"酒店标识可能被分词为单个词,搜索时可以将"商业区"用引号括起来表示短语匹配:
"query": "(地铁 OR \"商业区\") AND 7天"
三、精确查询(Term-level Queries)
1. 使用场景
●用户ID精确查找
●订单状态筛选
●价格范围查询
●日期区间查询
●需要精确匹配而非文本分析的场景
2. 核心查询类型
(1)term查询(精确匹配)
javascript
GET /indexName/_search
{
"query": {
"term": {
"status": "active" // 不进行分词,直接匹配
}
}
}
案例测试:
javascript
GET /hotel/_search
{
"query": {
"term": {
"business": "宝安商业区"
}
}
}
案例结果:
(2)terms查询(多值精确匹配)
javascript
GET /indexName/_search
{
"query": {
"terms": {
"tags": ["java", "elasticsearch", "分布式"]
}
}
}
案例测试:
javascript
GET /hotel/_search
{
"query": {
"terms": {
"name": ["如家酒店","机场"]
}
}
}
案例结果:
(3)range查询(范围查询)
javascript
GET /indexName/_search
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 500,
"boost": 2.0 // 权重
}
}
}
}
案例测试:
javascript
GET /hotel/_search
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 140
}
}
},
"from": 0,
"size": 100,
"sort": [
{"price": "asc"}
]
}
注:这里加了分页和排序,按照价格从低到高
案例结果:
(4)exists查询(字段存在性检查)
javascript
GET /indexName/_search
{
"query": {
"exists": {
"field": "description"
}
}
}
案例测试:
javascript
GET /hotel/_search
{
"query": {
"exists": {
"field": "city"
}
},
"from": 0,
"size": 100,
"sort": [
{"price": "asc"}
]
}
案例结果:
(5)bool组合查询(逻辑组合)
javascript
GET /indexName/_search
{
"query": {
"bool": {
"must": [
{"term": {"status": "active"}},
{"range": {"price": {"gte": 100}}}
],
"filter": [ // filter过滤,但不参与评分
{"term": {"category": "electronics"}}
],
"should": [ // 可选条件
{"term": {"is_recommended": true}}
],
"minimum_should_match": 1
}
}
}
注:minimum_should_match只影响bool查询中的should部分,minimum_should_match参数用于控制should子句中的匹配条件,它指定了在should子句中至少需要匹配多少个条件才能使整个bool查询匹配。
案例测试:
寻找在上海,打分超过40分以上,价格不超过200元,且是如家的酒店,可选条件是二钻:
javascript
{
"query": {
"bool": {
"must": [
{"term": {"city": "上海"}},
{"range": {"price": {"lte": 200}}},
{"range": {"score": {"gte": 40}}}
],
"filter": [
{"term": {"brand": "如家"}}
],
"should": [
{"term": {"starName": "二钻"}}
],
"minimum_should_match": 1
}
}
}
案例结果:
四、地理查询(Geo Queries)
此场景不再举例子,大家按照需要查询关键坐标匹配即可。
1. 使用场景
●附近商家搜索
●物流配送范围查询
●基于地理位置的推荐系统
●轨迹分析
2. 核心查询类型
(1)geo_distance查询(距离查询)
javascript
GET /indexName/_search
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "10km",
"location": { // 中心点坐标
"lat": 39.57,
"lon": 106.55
}
}
}
}
}
}
(2)geo_bounding_box查询(矩形区域查询)
javascript
GET /indexName/_search
{
"query": {
"bool": {
"filter": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 30.0,
"lon": 106.0
},
"bottom_right": {
"lat": 29.0,
"lon": 107.0
}
}
}
}
}
}
}
(3)geo_polygon查询(多边形区域查询)
javascript
GET /indexName/_search
{
"query": {
"bool": {
"filter": {
"geo_polygon": {
"location": {
"points": [
{"lat": 30.0, "lon": 106.0},
{"lat": 30.0, "lon": 107.0},
{"lat": 29.0, "lon": 107.0},
{"lat": 29.0, "lon": 106.0}
]
}
}
}
}
}
}
(4)geo_shape查询(复杂形状查询)
javascript
GET /indexName/_search
{
"query": {
"bool": {
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope", // 矩形
"coordinates": [[106.0, 30.0], [107.0, 29.0]]
},
"relation": "intersects" // 空间关系
}
}
}
}
}
}
五、性能优化建议
1、全文检索优化:
●合理设置分词器
●使用minimum_should_match控制匹配精度
●避免在高频字段上使用match_all
2、精确查询优化:
●为常用精确查询字段设置keyword类型
●使用filter上下文提高缓存效率
●避免在bool查询中嵌套过多条件
3、地理查询优化:
●使用geo_point类型存储地理位置
●对地理查询使用filter上下文
●合理设置distance_type(arc/plane)
下一篇我们继续讲解DSL查询语法中"相关性算分"、"FunctionScoreQuery"和"BooleanQuery"的相关内容。
转载请注明出处:https://blog.csdn.net/acmman/article/details/148195366