一、概述
Elasticsearch 是一款全文搜索引擎,可以轻松地处理海量数据。它提供了一种查询语言,称为查询 DSL,用于在索引中搜索数据。查询 DSL 的语法是基于 JSON 的,允许您构建复杂的查询和聚合操作。
查询 DSL 语言的核心是查询语句(Query Clauses),它们定义了要匹配的查询条件。查询语句可以分为两类:
- 查询子句(Query Clauses):用于确定哪些文档匹配查询条件。
- 过滤子句(Filter Clauses):用于限制查询的结果集。
查询子句通常用于评分(Scoring)和排序(Sorting)操作,而过滤子句则更适合用于筛选数据。
以下是一些常见的查询子句和过滤子句:
- term 查询(Term Query):匹配一个精确值,例如一个单词或一个数字。
- match 查询(Match Query):匹配一个查询字符串中的一个或多个单词。
- range 查询(Range Query):匹配一个数值范围。
- bool 查询(Boolean Query):组合多个查询子句,可以使用 AND、OR 或 NOT 运算符。
- exists 过滤(Exists Filter):匹配存在指定字段的文档。
- missing 过滤(Missing Filter):匹配不存在指定字段的文档。
- term 过滤(Term Filter):匹配一个精确值。
- range 过滤(Range Filter):匹配一个数值范围。
- bool 过滤(Boolean Filter):组合多个过滤子句,可以使用 AND、OR 或 NOT 运算符。
二、查询子句
term 查询
term 查询用于匹配一个精确值。它通常用于匹配文本字段或数字字段。以下是一个示例:
上面的查询将匹配所有 name
字段值为 "John" 的文档。请注意,term 查询是区分大小写的。
match 查询
match 查询用于匹配一个查询字符串中的一个或多个单词。它通常用于匹配文本字段。以下是一个示例
上面的查询将匹配所有 title
字段包含单词 "Elasticsearch" 的文档。请注意,match 查询是不区分大小写的。
match 查询还支持一些高级选项,例如模糊匹配、词组匹配和前缀匹配等。以下是一些示例:
上面的查询将匹配所有 title
字段包含 "Elasticsearch" 和 "server" 两个单词的文档,同时允许模糊匹配(fuzziness)。
上面的查询将匹配所有 title
字段包含 "Elasticsearch server" 这个词组的文档,同时允许一个单词的间隔(slop)。
上面的查询将匹配所有 title
字段以 "Elastic" 开头的词组,同时允许最多 10 个扩展词。
range 查询
range 查询用于匹配一个数值范围。它通常用于匹配数字字段。以下是一个示例:
上面的查询将匹配所有 age
字段值在 18 到 30 之间的文档。range 查询还支持其他选项,例如大于(gt)、小于(lt)等。
bool 查询
bool 查询用于组合多个查询子句,可以使用 AND、OR 或 NOT 运算符。以下是一个示例:
上面的查询将匹配所有 title
字段包含 "Elasticsearch",且 description
字段包含 "distributed",同时不包含 category
字段值为 "xxx" 的文档。此外,它应该(should)包含 "Smith" 或 "John" 作为 author
字段的值,但最少需要匹配一个(minimum_should_match)。
三、过滤子句
过滤子句用于过滤文档,与查询不同,过滤不会影响文档的评分。因此,如果您只是想筛选出一些文档,而不需要对其进行排序和评分,过滤子句是更好的选择。
exists 过滤
exists 过滤用于筛选出包含指定字段的文档。以下是一个示例:
上面的过滤将返回所有包含 title
字段的文档。
term 过滤
term 过滤用于精确匹配指定字段的值。以下是一个示例:
上面的过滤将返回所有 status
字段值为 "published" 的文档。
range 过滤
range 过滤用于匹配一个数值范围。它通常用于匹配数字字段。以下是一个示例:
上面的过滤将返回所有 age
字段值在 18 到 30 之间的文档。range 过滤还支持其他选项,例如大于(gt)、小于(lt)等。
bool 过滤
bool 过滤用于组合多个过滤子句,可以使用 AND、OR 或 NOT 运算符。以下是一个示例:
上面的过滤将返回所有 status
字段值为 "published",且 age
字段值大于等于 18,同时不包含 category
字段值为 "xxx" 的文档。此外,它应该(should)包含 "Smith" 或 "John" 作为 author
字段的值,但最少需要匹配一个(minimum_should_match)。
四、排序
排序用于对文档进行排序,可以按一个或多个字段进行排序。以下是一个示例:
上面的排序将按 created_at
字段降序排序,如果有相同的值,则按 views
字段降序排序。
五、聚合
聚合用于对文档进行统计分析,例如计算某个字段的平均值、最大值、最小值、总和等。Elasticsearch 支持多种聚合类型,包括指标聚合、桶聚合、管道聚合等。
指标聚合
指标聚合用于计算某个字段的值,例如平均值、最大值、最小值、总和等。以下是一个示例:
上面的聚合将计算 price
字段的平均值,并将结果存储在 avg_price
中。
桶聚合
桶聚合用于将文档分配到不同的桶中,例如根据某个字段的值分组。以下是一个示例:
上面的聚合将根据 genre
字段的值将文档分配到不同的桶中,并将每个桶的文档数量返回。
管道聚合
管道聚合用于在多个聚合之间构建一个聚合流水线,将前一个聚合的结果作为后一个聚合的输入。以下是一个示例:
上面的聚合将按照 created_at
字段的年份分组,并计算每年的总销售额和平均销售额。
六、Java API
除了使用 REST API 外,您还可以使用 Elasticsearch 的 Java API 进行查询、过滤、排序和聚合操作。以下是一些示例代码:
创建索引
上面的代码将创建一个名为 my-index
的索引,并插入一条文档。
查询文档
上面的代码将查询 my-index
索引中所有 title
字段包含 "Elasticsearch" 的文档,并打印它们的 JSON 格式。
过滤文档
上面的代码将查询 my-index
索引中所有 title
字段包含 "Elasticsearch",且 price
字段的值在 10 和 100 之间的文档,并打印它们的 JSON 格式。
排序文档
上面的代码将查询 my-index
索引中所有 title
字段包含 "Elasticsearch" 的文档,并按照 price
字段的值进行升序排序,并打印它们的 JSON 格式。
聚合文档
上面的代码将查询 my-index
索引中 price
字段的平均值,并打印结果。
总结
本文介绍了 Elasticsearch 的查询 DSL 语言,包括查询、过滤、排序和聚合操作,以及 Java API 的使用方法。了解 Elasticsearch 的查询语言可以帮助您更好地理解和使用 Elasticsearch,提高数据检索的效率和准确性。
常见问题
1. 查询性能如何优化?
查询性能的优化是 Elasticsearch 中最重要的优化之一。以下是一些优化查询性能的方法:
- 索引的字段数量应该保持在适当的范围内,过多的字段会增加索引的大小,降低查询的速度。
- 将经常被查询的字段存储为关键字字段,可以提高查询的速度。
- 通过过滤器过滤掉不需要的文档,可以减少查询的范围,提高查询的速度。
- 使用正确的查询语句,如 term 查询比 match 查询更快。
也可以参考我的往期文章 Elasticsearch索引优化指南:分片、副本、mapping和analyzer
2. 如何进行模糊搜索?
在 Elasticsearch 中,可以使用模糊搜索来找到与搜索词相似的文档。以下是一些常见的模糊搜索方法:
- 使用通配符搜索,如使用 * 号匹配任意字符,使用 ? 号匹配单个字符。
- 使用模糊搜索,如使用 ~ 符号指定模糊搜索的程度。
- 使用距离搜索,如使用距离参数指定搜索词的编辑距离。
3. 如何实现全文搜索?
全文搜索是 Elasticsearch 中最常用的搜索之一,以下是一些实现全文搜索的方法:
- 将需要搜索的字段定义为文本类型,这样 Elasticsearch 就会对这些字段进行分词处理。
- 使用 match 查询进行全文搜索。
- 使用多字段搜索来搜索多个字段。
- 使用高亮显示来突出显示匹配的文本。
4. 如何实现分页搜索?
分页搜索是 Elasticsearch 中常用的搜索之一,以下是一些实现分页搜索的方法:
- 使用 from 和 size 参数来指定需要返回的文档范围。
- 使用 scroll 查询来获取所有文档,并进行分页处理。
- 使用 search_after 查询来实现基于游标的分页。
5. 如何实现复杂的搜索逻辑?
在实际应用中,很多搜索逻辑都比较复杂,以下是一些实现复杂的搜索逻辑的方法:
- 使用复合查询,如 bool 查询、dis_max 查询、function_score 查询等。
- 使用多个查询组合在一起进行搜索。
- 使用过滤器过滤掉不需要的文档。
也可参考我的往期文章从入门到进阶:Elasticsearch高级查询技巧详解