Query DSL
Elastic Stack Serverless
Query DSL 是一种功能齐全的 JSON 风格的查询语言,可以实现复杂的搜索、过滤和聚合。它是当今 Elasticsearch 最原始且最强大的查询语言。
_search
端点接受用 Query DSL 语法编写的查询。
Query DSL 支持各种搜索技术,包括以下内容
- 全文搜索:搜索已分析和索引的文本,以支持短语或邻近查询、模糊匹配等。
- 关键词搜索:使用
keyword
字段搜索完全匹配项。 - 语义搜索:使用在 Elasticsearch 集群中生成的嵌入上的密集或稀疏向量搜索来搜索
semantic_text
字段。 - 向量搜索:使用 kNN 算法搜索相似的密集向量,这些向量在 Elasticsearch 外部生成。
- 地理空间搜索:使用地理空间查询搜索位置并计算空间关系。
您还可以使用 Query DSL 过滤数据。过滤器允许您通过检索与特定字段级条件匹配的文档来包含或排除文档。使用 filter
参数的查询表示 过滤上下文。
聚合是使用 Query DSL 分析 Elasticsearch 数据的主要工具。聚合使您能够构建数据的复杂摘要,并深入了解关键指标、模式和趋势。
由于聚合利用了与搜索相同的数据结构,因此它们也非常快。这使您可以实时分析和可视化您的数据。您可以同时在同一数据上、在单个请求中搜索文档、过滤结果和执行分析。这意味着聚合是在搜索查询的上下文中计算的。
以下聚合类型可用
通过指定 搜索 API 的 aggs
参数来运行聚合。 在 运行聚合中了解更多信息。
将 Query DSL 视为查询的 AST(抽象语法树),由两种类型的子句组成
叶子查询子句:叶子查询子句在特定字段中查找特定值,例如 match
、term
或 range
查询。 这些查询可以单独使用。
复合查询子句:复合查询子句包装其他叶子或复合查询,用于以逻辑方式组合多个查询(例如 bool
或 dis_max
查询),或改变它们的行为(例如 constant_score
查询)。
查询子句的行为因它们是在 查询上下文还是过滤上下文中使用而异。
允许高代价的查询:某些类型的查询由于其实现方式,通常执行速度较慢,这可能会影响集群的稳定性。 这些查询可以分为以下几类
需要进行线性扫描以识别匹配项的查询
具有高前期成本的查询
可能具有高文档成本的查询
可以通过将 search.allow_expensive_queries
设置的值设置为 false
来阻止此类查询的执行(默认为 true
)。
默认情况下,Elasticsearch 按相关性得分对匹配的搜索结果进行排序,相关性得分衡量每个文档与查询的匹配程度。
相关性得分是一个正浮点数,在 搜索 API 的 _score
元数据字段中返回。 _score
越高,文档的相关性越高。虽然每种查询类型计算相关性得分的方式可能不同,但得分计算还取决于查询子句是在查询还是过滤上下文中运行。
在查询上下文中,查询子句回答了以下问题:此文档与此查询子句的匹配程度如何? 除了决定文档是否匹配之外,查询子句还会在 _score
元数据字段中计算相关性得分。
只要查询子句传递给 query
参数,查询上下文就有效,例如 搜索 API 中的 query
参数。
过滤器回答了二元问题“此文档是否与此查询子句匹配?”。 答案很简单“是”或“否”。 过滤具有以下几个好处
- 简单的二元逻辑:在过滤上下文中,查询子句基于是/否标准确定文档匹配项,而无需计算得分。
- 性能:由于它们不计算相关性得分,因此过滤器比查询执行得更快。
- 缓存:Elasticsearch 会自动缓存常用过滤器,从而加快后续搜索性能。
- 资源效率:与全文查询相比,过滤器消耗的 CPU 资源更少。
- 查询组合:过滤器可以与评分查询组合,以有效地优化结果集。
过滤器对于查询结构化数据和在复杂搜索中实现“必须具有”条件特别有效。
结构化数据是指以预定义方式高度组织和格式化的信息。 在 Elasticsearch 的上下文中,这通常包括
- 数字字段(整数、浮点数)
- 日期和时间戳
- 布尔值
- 关键字字段(完全匹配字符串)
- 地理点和地理形状
与全文字段不同,结构化数据具有一致的、可预测的格式,使其成为精确过滤操作的理想选择。
常见的过滤器应用包括
- 日期范围检查:例如,
timestamp
字段是否在 2015 年到 2016 年之间 - 特定字段值的检查:例如,
status
字段是否等于 "published",或者author
字段是否等于 "John Doe"。
当查询子句传递给 filter
参数时,应用过滤器上下文,例如:
bool
查询中的filter
或must_not
参数constant_score
查询中的filter
参数filter
聚合
过滤器可以优化查询性能和效率,尤其适用于结构化数据查询以及与全文搜索结合使用。
以下是 search
API 中查询子句在查询上下文和过滤器上下文中使用的示例。 此查询将匹配满足以下所有条件的文档:
title
字段包含单词search
。content
字段包含单词elasticsearch
。status
字段包含精确的单词published
。publish_date
字段包含自 2015 年 1 月 1 日起的日期。
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
query
参数表示查询上下文。bool
和两个match
子句用于查询上下文中,这意味着它们用于对每个文档的匹配程度进行评分。filter
参数表示过滤器上下文。其term
和range
子句在过滤器上下文中使用。它们将过滤掉不匹配的文档,但不会影响匹配文档的分数。
在查询上下文中计算的查询分数表示为单精度浮点数;它们只有 24 位有效位数。 超过有效位数的精度计算将被转换为浮点数,从而导致精度损失。
对于应该影响匹配文档分数的条件(即文档的匹配程度),在查询上下文中使用查询子句,并在过滤器上下文中使用所有其他查询子句。