Elasticsearch(ES)基础查询语法的使用
1. Match Query (全文检索查询)
- 用于执行全文检索,适合搜索文本字段。
{ \"query\": { \"match\": { \"field\": \"value\" } }}
- match_phrase:精确匹配短语,适合用于短语搜索。
{ \"query\": { \"match_phrase\": { \"field\": \"text\" } }}
2. Term Query (精确匹配查询)
- 用于对某个字段的精确值进行查询,常用于不分词的字段(如ID、标签、关键词等)。
{ \"query\": { \"term\": { \"field\": \"value\" } }}
3. Range Query (范围查询)
- 用于查询数值、日期、时间等范围内的数据。
{ \"query\": { \"range\": { \"field\": { \"gte\": 10, // 大于等于 \"lte\": 100, // 小于等于 \"gt\": 10, // 大于 \"lt\": 100 // 小于 } } }}
4. Bool Query (布尔查询)
- 用于将多个查询组合在一起,可以使用 must、should、must_not 等操作符。
{ \"query\": { \"bool\": { \"must\": [ { \"match\": { \"field1\": \"value1\" } }, { \"match\": { \"field2\": \"value2\" } } ], \"filter\": [ { \"range\": { \"price\": { \"gte\": 50 } } } ], \"should\": [ { \"match\": { \"field3\": \"value3\" } } ], \"must_not\": [ { \"term\": { \"field4\": \"value4\" } } ] } }}
5. Prefix Query (前缀匹配查询)
- 用于查询字段值的前缀匹配,常用于搜索补全或模糊搜索。
{ \"query\": { \"prefix\": { \"field\": \"prefix_value\" } }}
6. Wildcard Query (通配符查询)
- 支持
*
(匹配任意字符)和?
(匹配单个字符)的通配符查询。
{ \"query\": { \"wildcard\": { \"field\": \"prefix*\" } }}
7. Fuzzy Query (模糊查询)
- 用于查询与某个值相似的字段,常用于容忍拼写错误的场景。
{ \"query\": { \"fuzzy\": { \"field\": { \"value\": \"exampl\" } } }}
8. Regexp Query (正则表达式查询)
- 使用正则表达式进行查询。
{ \"query\": { \"regexp\": { \"field\": \"pattern.*\" } }}
9. Match All Query (匹配所有文档)
- 用于返回索引中的所有文档。
{ \"query\": { \"match_all\": {} }}
10. Term Range Query (字段范围查询)
- 用于查询一个字段值在特定范围内的文档,类似
range query
,但term
查询是基于精确值的。
{ \"query\": { \"range\": { \"field\": { \"gte\": 5, \"lte\": 10 } } }}
11. Exists Query (字段存在查询)
- 用于查询某个字段是否存在。
{ \"query\": { \"exists\": { \"field\": \"field_name\" } }}
12. Geo Queries (地理位置查询)
- Elasticsearch 支持基于地理位置的查询,如基于位置的范围查询或距离查询。
- Geo Distance Query
{ \"query\": { \"bool\": { \"filter\": { \"geo_distance\": { \"distance\": \"200km\", \"location\": { \"lat\": 40.73, \"lon\": -74.1 } } } } }}
13. Aggregation (聚合查询)
- Elasticsearch 提供了强大的聚合功能,可以对查询结果进行分组、统计等操作。
- Terms Aggregation (分词聚合)
{ \"aggs\": { \"group_by_field\": { \"terms\": { \"field\": \"field_name\" } } }}
- Range Aggregation (范围聚合)
{ \"aggs\": { \"price_ranges\": { \"range\": { \"field\": \"price\", \"ranges\": [ { \"to\": 100 }, { \"from\": 100, \"to\": 200 }, { \"from\": 200 } ] } } }}
14. Highlighting (高亮查询)
- 用于返回搜索结果中高亮显示匹配的字段。
{ \"query\": { \"match\": { \"field\": \"value\" } }, \"highlight\": { \"fields\": { \"field\": {} } }}
15. Source Filtering (源字段过滤)
- 用于控制哪些字段需要返回,哪些不需要返回。
{ \"_source\": [\"field1\", \"field2\"], \"query\": { \"match\": { \"field\": \"value\" } }}
16. Prefix and Wildcard Query (前缀和通配符查询)
- 用于对字段值进行前缀或通配符匹配,常用于实现补全或模糊搜索。
{ \"query\": { \"prefix\": { \"field\": \"prefix*\" } }}
扩展*
匹配度查询
在 Elasticsearch 中,minimum_should_match
是布尔查询(bool
query)的一部分,用于控制 should
子句的匹配度。should
子句的作用是定义一组可选条件,当文档满足其中至少一个条件时,它会被视为匹配。通过设置 minimum_should_match
参数,可以控制至少多少个 should
子句必须匹配,以提高查询的精度和灵活性。
1. 基本概念:
- 在布尔查询中,
should
子句表示可选条件。 - 默认情况下,如果
bool
查询中有多个should
子句,文档只需满足其中任何一个条件就可以匹配。 - 使用
minimum_should_match
参数,可以要求文档至少满足某些数量的should
子句,以增加查询的严格性。
例如:如果你有 5 个 should
子句,并设置 minimum_should_match
为 3,则文档必须满足其中至少 3 个 should
条件才能被视为匹配。
2. 用法:
minimum_should_match
可以设置为:
- 整数值:指定最小匹配的
should
子句数量。 - 百分比:指定至少要匹配的
should
子句的百分比。 - 动态值:例如基于文档数量或其他复杂逻辑的动态匹配要求。
3. 示例:
(1) 简单的布尔查询 - 至少匹配 2 个 should
子句
{ \"query\": { \"bool\": { \"should\": [ { \"match\": { \"field1\": \"value1\" } }, { \"match\": { \"field2\": \"value2\" } }, { \"match\": { \"field3\": \"value3\" } } ], \"minimum_should_match\": 2 // 至少匹配 2 个 `should` 子句 } }}
- 在这个例子中,文档需要匹配至少 2 个
should
子句(例如,匹配field1
和field2
或者field2
和field3
)。
(2) 使用百分比的 minimum_should_match
如果你有多个 should
子句,可以通过百分比来控制匹配条件。例如,如果你有 5 个 should
子句,设置 minimum_should_match
为 60%,则至少需要满足 3 个子句。
{ \"query\": { \"bool\": { \"should\": [ { \"match\": { \"field1\": \"value1\" } }, { \"match\": { \"field2\": \"value2\" } }, { \"match\": { \"field3\": \"value3\" } }, { \"match\": { \"field4\": \"value4\" } }, { \"match\": { \"field5\": \"value5\" } } ], \"minimum_should_match\": \"60%\" // 至少匹配 60% 的 `should` 子句 (即 3 个子句) } }}
(3) 动态匹配 - 基于词数的 minimum_should_match
还可以根据查询中的词数设置 minimum_should_match
,比如设置为 \"3<80%\"
,表示如果查询中有 3 个以上的 should
子句,则至少匹配其中 80%的子句。
{ \"query\": { \"bool\": { \"should\": [ { \"match\": { \"field1\": \"value1\" } }, { \"match\": { \"field2\": \"value2\" } }, { \"match\": { \"field3\": \"value3\" } }, { \"match\": { \"field4\": \"value4\" } }, { \"match\": { \"field5\": \"value5\" } } ], \"minimum_should_match\": \"3<80%\" // 如果有超过 3 个 `should` 子句,至少匹配 80% } }}
4. 如何决定 minimum_should_match
值
- 业务需求:设置
minimum_should_match
的主要目的是根据业务需求平衡准确度和召回率。如果你需要更严格的匹配,增加minimum_should_match
的值;如果需要更高的召回率,可以减少它。 - 文档内容:在处理文档时,字段的长度、词汇密度、停用词等都可能影响查询的结果。可以通过实验和调整
minimum_should_match
来找到最适合的设置。
5. 示例:
假设你有以下文档数据:
{ \"field1\": \"apple orange banana\", \"field2\": \"apple orange\", \"field3\": \"banana\"}
你要查找包含 “apple” 和 “orange” 的文档,并且需要设置 minimum_should_match
为 1。查询语句如下:
{ \"query\": { \"bool\": { \"should\": [ { \"match\": { \"field1\": \"apple\" } }, { \"match\": { \"field1\": \"orange\" } }, { \"match\": { \"field1\": \"banana\" } } ], \"minimum_should_match\": 1 } }}
在这个例子中,只要文档匹配一个 should
子句(比如 field1
包含 “apple” 或者 “orange”),就会被视为匹配。
6. 注意事项
minimum_should_match
在布尔查询中是可选的,只有当你使用了多个should
子句时才有意义。- 设置的值越大,匹配条件越严格。通过调整
minimum_should_match
的值,可以灵活地调整查询的宽松程度。 minimum_should_match
参数可以通过数值、百分比、动态规则来设置,以适应不同的查询需求。
7. Match 查询的选项
(1) fuzziness
:模糊匹配
如果你希望支持拼写错误或词语变化,可以使用 模糊查询。通过设置 fuzziness
,Elasticsearch 会尝试匹配与查询词相似的词。
{ \"query\": { \"match\": { \"title\": { \"query\": \"Elasticsearh\", // 拼写错误 \"fuzziness\": \"AUTO\" // 自动模糊匹配 } } }}
fuzziness: \"AUTO\"
:根据查询词的长度自动设置模糊匹配的编辑距离。fuzziness: \"1\"
:设置允许的最大编辑距离为 1(允许 1 个字符的更改,如替换、删除、插入)。
(2) minimum_should_match
:最小匹配
在某些情况下,你可能想要求查询中至少匹配一个或多个词。minimum_should_match
可以控制需要匹配的最小词数。
{ \"query\": { \"match\": { \"content\": { \"query\": \"Elasticsearch tutorial advanced\", \"minimum_should_match\": 2 // 至少匹配 2 个词也可以用百分比替代示例:\"60%\"(指匹配总分词的百分比) } } }}
minimum_should_match
:设置至少要匹配多少个词。
(3) boost
:提高某个词的匹配优先级
你可以通过 boost
来提高查询某些词的权重,使这些词匹配的文档更具优先级。
{ \"query\": { \"match\": { \"content\": { \"query\": \"Elasticsearch tutorial\", \"boost\": 2.0 // 增加查询的权重,使该查询匹配的文档优先返回 } } }}
boost
:提高查询的匹配优先级,权重范围通常是 0 到 10,数值越大,匹配的优先级越高。
** match
查询常见问题**
(1) 如何处理大小写问题?
默认情况下,match
查询不区分大小写。Elasticsearch 会使用分词器(如 standard
分词器)将文本转为小写,因此可以处理大小写问题。
(2) match
查询与 term
查询的区别
match
查询:适用于文本字段的分词匹配,会分析查询文本并与字段内容进行分词对比。term
查询:用于精确匹配,适用于不分词的字段(如keyword
字段)。
聚合相关
在 Elasticsearch 中,**聚合(Aggregation)**是一个强大的功能,用于对查询结果进行分组、统计、度量等操作。聚合查询不仅可以按字段进行分组,还可以进行计算(如求和、平均值等),在数据分析和可视化中非常有用。聚合查询和普通查询(例如 match
、range
查询)是分开的,但可以结合使用。
1. 聚合查询的基本结构
聚合查询通常包含在 aggs
(聚合)部分。在 Elasticsearch 中,聚合查询并不返回实际的文档,而是返回聚合结果,例如每个分组的文档数量、平均值、最大值等。
聚合查询的基本结构:
{ \"query\": { \"match\": { \"field\": \"value\" } }, \"aggs\": { \"aggregation_name\": { \"aggregation_type\": { \"field\": \"field_name\" } } }}
2. 常见的聚合类型
以下是 Elasticsearch 中常见的聚合类型:
(1) Terms 聚合(分词聚合)
按字段值进行分组统计,返回每个字段值及其出现次数。常用于进行分组查询。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"group_by_field\": { \"terms\": { \"field\": \"field_name\" } } }}
示例:
假设你有一个名为 category
的字段,你想按类别进行分组查询,统计每个类别的文档数量。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"categories\": { \"terms\": { \"field\": \"category.keyword\" // 使用 .keyword 进行精确匹配 } } }}
(2) Range 聚合(范围聚合)
用于按指定的数值范围对文档进行分组。适用于数值、日期等字段。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"price_ranges\": { \"range\": { \"field\": \"price\", \"ranges\": [ { \"to\": 50 }, { \"from\": 50, \"to\": 100 }, { \"from\": 100 } ] } } }}
示例:
假设你想要按价格进行分段统计,例如分为“低于 50”、“50 到 100”以及“大于 100”三个区间。
(3) Avg 聚合(平均值聚合)
用于计算字段的平均值。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"average_price\": { \"avg\": { \"field\": \"price\" } } }}
示例:
计算 price
字段的平均值。
(4) Sum 聚合(求和聚合)
用于计算字段的总和。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"total_price\": { \"sum\": { \"field\": \"price\" } } }}
示例:
计算 price
字段的总和。
(5) Max 和 Min 聚合(最大值和最小值聚合)
用于计算字段的最大值和最小值。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"max_price\": { \"max\": { \"field\": \"price\" } }, \"min_price\": { \"min\": { \"field\": \"price\" } } }}
示例:
计算 price
字段的最大值和最小值。
(6) Date Histogram 聚合(日期直方图聚合)
将日期数据按时间段进行分组,常用于按天、周、月等时间单位进行聚合。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"sales_over_time\": { \"date_histogram\": { \"field\": \"timestamp\", \"calendar_interval\": \"day\" // 按天分组 } } }}
示例:
按天统计销售数据。
(7) Top Hits 聚合(获取 top N 文档)
获取符合条件的 top N 文档,通常用于获取聚合组中的部分文档,适用于展示最高分的文档。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"top_categories\": { \"terms\": { \"field\": \"category.keyword\" }, \"aggs\": { \"top_hits\": { \"top_hits\": { \"size\": 3 // 返回每个类别下的前 3 个文档 } } } } }}
(8) Cardinality 聚合(基数聚合)
用于计算字段的基数(去重后的唯一值数量)。例如,统计不同的用户数或产品数。
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"unique_users\": { \"cardinality\": { \"field\": \"user_id\" } } }}
示例:
计算 user_id
字段中不重复的用户数量。
3. 聚合嵌套
聚合查询不仅可以进行单一聚合,还可以进行嵌套聚合,即在一个聚合的结果上进行进一步的聚合。下面是一个例子,展示如何在一个 terms
聚合的每个分组上执行进一步的聚合:
{ \"query\": { \"match_all\": {} }, \"aggs\": { \"categories\": { \"terms\": { \"field\": \"category.keyword\" }, \"aggs\": { \"avg_price\": { \"avg\": { \"field\": \"price\" } } } } }}
示例:
先按 category
分组,再计算每个类别的平均价格。
4. 聚合结果的格式
聚合查询的结果会包含在 aggregations
(或 aggs
)字段中。结果结构通常类似于下面的格式:
{ \"aggregations\": { \"categories\": { \"buckets\": [ { \"key\": \"electronics\", // 分组的字段值 \"doc_count\": 100, // 每个分组的文档数量 \"avg_price\": { \"value\": 300 // 每个分组的聚合结果,如平均价格 } }, { \"key\": \"clothing\", \"doc_count\": 80, \"avg_price\": { \"value\": 50 } } ] } }}
聚合结果:
buckets
:每个分组的结果集合。key
:分组的字段值。doc_count
:该分组中的文档数量。- 聚合结果(例如
avg_price
):聚合操作的结果。
5. 聚合的性能优化
- 避免过多的
terms
聚合:terms
聚合会对字段值进行分组,可能会消耗大量内存和计算资源。对于高基数字段(如用户ID),考虑限制返回的分组数量。 - 限制返回的文档数量:可以通过
size
参数来限制每个分组返回的文档数量,避免过多数据返回。 - 减少聚合的嵌套深度:过多层次的嵌套聚合会增加 Elasticsearch 的计算负担,尽量保持聚合的平面结构。