共计 1348 个字符,预计需要花费 4 分钟才能阅读完成。
查询语法(Query DSL)
Elasticsearch 提供标准 RESTful 风格的查询 DSL 来定义查询。可以将查询 DSL 看作是由两种子句组成的查询的 AST (Abstract Syntax Tree):
Leaf query clauses
叶查询语句(可以理解为 SQL 里的 where 查询)在特定字段中查找特定值,例如 match,term 或 range 查询,这些查询同时也可以单独使用。
Compound query clauses
复合查询语句可以组合 Leaf Query 和 Compound Query,用于以组合多个查询,或者更改其行为(例如 constant_score 查询)。
查询语句行为的不同取决于它们是在查询上下文还是过滤器上下文中使用。
查询上下文和过滤上下文
查询子句的行为取决于它是在查询上下文中使用还是在过滤上下文中使用:
查询上下文
在查询上下文中使用的查询子句会回答这个问题:“此文档与此查询子句的匹配程度怎么样?”除了决定文档是否匹配之外,查询子句还会计算一个评分,用来表示文档的匹配度。
只要将查询子句传递给 query 参数 (比如 Search API 中的 query 参数),查询上下文就会生效。
过滤上下文
在过滤上下文中,查询子句回答以下问题:” 此文档与此查询子句匹配吗?” 答案只有是或否,不计算评分。过滤上下文主要用于过滤结构化的数据,例如:
这个时间是否在 2015 到 2016 年之间?
状态是不是已发布?
经常使用的过滤器将被 Elasticsearch 自动缓存,以提高性能。
只要将查询子句传递给 filter(如 bool 查询中的 filter 或 must not,constant_score 查询中的 filter 或 aggregation 中的 filter),过滤上下文就会生效。
一些例子
那怎么判断自己的 dsl 是查询上下文还是过滤上下文呢?以下给出一些解释
基础查询都属于查询上下文
{
“query”:{
“term/range/terms/match/match_phrase”:{}
}
}
constant_score 比较特殊,虽然看着是基础查询,但是他是固定评分查询,所以也属于过滤上下文
{
“query”:{
“constant_score”:{}
}
}
bool 查询中的 filter 属于过滤上下文
{
“query”:{
“bool”:{
//filter 这里可以定义对象,单个过滤子句,也可以定义数组,多个过滤条件
“filter”:[]
“filter”:{}
}
}
}
bool 查询中的 must not 属于过滤上下文
{
“query”:{
“bool”:{
“mustnot”:[]
}
}
}
agg 聚合查询中的 filter agg 也属于过滤上下文
{
“aggs”:{
“t_shirts” : {
“filter” : {“term”: { “type”: “t-shirt”} },
“aggs” : {
“avg_price” : {“avg” : { “field” : “price”} }
}
}
}
}
那么问题来了,如果我在 bool/filter 中嵌套了 boolean/must 子句,那这里的 must 子句到底是查询上下文还是过滤上下文呢?
{
“query”:{
“bool”:{
“filter”:{
“bool”:{
“must”:{
//query cause
}
}
}
}
}
}
答案是处于过滤上下文,上下文的判断基于顶层语句