elk笔记13--Query DSL
- 2.1 Query and filter context
- 2.2 Compound queries
- 2.3 Full text queries
- 2.4 Geo queries
- 2.5 Joining queries
- 2.6 Match all query
- 2.7 Span queries
- 2.8 Specialized queries
- 2.9 Term-level queries
- 2.10 minimum_should_match parameter
- 2.11 rewrite parameter
- 2.12 Regular expression syntax
- 3 常见查询案例
- 4 注意事项
- 5 说明
1 基础介绍
ES 提供了一个丰富的查询DSL(领域特有语言),该语言基于json来定义各种请求。把查询DSL看作为查询的抽象树(AST), 其包含两类使用条款|形式。
第一类:叶子查询子句,该子句在特定的字段中查找特定的值,例如match、term、range查询都属于这一类。这些查询可以被它们自己使用。
第二类:混合查询子句,该子句包含其它叶子查询或混合查询,被用于结合在一个逻辑使用样式(例如bool或者dis_max查询)中的多个查询,也可以用于修改查询的一些行为(例如constant_score query)。
基于查询是否在查询上下文或过滤上下文,查询子句表现会有所不同。
2 常见查询类型
2.1 Query and filter context
- 相关度分数(Relevance scores)
默认情况下,es 通过相关度分数对匹配的查询结果进行排序。相关度分数用于测量每个文档和查询的匹配程度。
相关度分数是一个正浮点数字,它在查询API的返回数据原字段为_score. 通常情况下,_score 越高,文档的相关度越高。es 中每个查询类型会计算出不同的相关度分数,相关度分数计算方式也取决于查询子句是否在请求上下文或者过滤上下文中进行。 - 查询上下文(Query context)
在一个查询上下文中,查询子句回答了"特定文档和查询子句匹配程"的问题。除了计算文档是否匹配,查询语句也计算了一个相关度分数,该值存在原字段的_score 中。
不论何时,只要一个查询子句被传递到一个查询参数中,查询上下文就会其作用,例如查询参数在查询API中。 - 过滤上下文(Filter context)
在一个过滤上下文中,查询子句回答了“文档是否匹配查询子句”的问题,其答案是一个简单的是或否,该方式中不计算相关度分数。过滤上线问最多被用于过滤结构数据中,例如:某个时间戳是否在2015-2016之间?字段status是否设置为 published?
es 为了加速其性能,会将频繁使用的过滤自动缓存起来。
不论何时,当一个查询子句被传递到一个过滤参数中时,过滤上下文将会起作用。例如:bool 查询中的filter或者must_not参数,constant_score 查询中的过滤参数,或者过滤聚合。
2.2 Compound queries
复合查询包裹着其它复合查询或叶子查询,它要么结合其它查询的结果和相关度分数,以改变它们的行为,要么从查询上下文切换到过滤上下文。
该范畴内的查询包括 bool查询、boosting查询、constant_score查询、dis_max 查询、function_score查询 等5大类,具体如下:
- bool query
bool 查询是结合多个叶子查询或者混合查询子句的默认查询,如must、should、must_not 或filter子句。其中,must和should子句有它们自己相关的分数,匹配的子句越多,相关度分数越好;然而,must_not和filter子句在filter上下文中执行,不参与相关度分数计算。 - boosting query
boosting查询返回匹配为积极查询的文档,同时减少匹配到为消极查询的文档扽相关度分数。其中,positive 和 negative 为boosting的顶层参数。 - constant_score query
constant_score 查询是指:当一个查询包含其它查询,但是在过滤上下文中执行的时候,所有匹配到的文档被赋予一个相同的固定值,默认为1.0。 - dis_max query
一个查询可以接受多个查询,并返回任何匹配到查询子句的文档。其中,bool 查询结合多个匹配查询的相关度分数得到一个最终的相关度分数,但dis_max使用单个查询子句中最好的那个查询的相关度分数做为最终的分数。
例如 bool:[{Query A},{Query B}], 在同时包含A和B的bool查询中,dis_max 返回A 和 B中分值最高的那个做为最终分数。 - function_score query
通过一些函数来修改主请求返回的分数,以便于将受欢迎程序、时间、距离或自定义的算法等因素考虑到相关度分数中。
2.3 Full text queries
全文检索允许用户查找被分析器分析的分词字段,例如一个邮件的正文。检索的字符串被之前写入时相同的分析器进行处理。
该范畴内的查询包括 intervals 查询、match 查询、match_bool_prefix 查询、match_phrase 查询、match_phrase_prefix 查询、multi_match 查询、common terms 查询、query_string 查询、simple_query_string 查询等9类,如下所示:
- intervals query
intervals 类型的全文检索,可以对匹配项的顺序和距离进行细粒度控制。 - match query
match 类型的全文检索是执行全文检索的标准查询方式,包括模糊匹配、词组查询或距离查询。 - match_bool_prefix query
match_bool_prefix 查询创建一个bool 查询,该查询匹配每个项为一个term 查询,除了最后一个项,因为最后一项做为一个前缀查询。 - match_phrase query
match_phrase 查询像match查询,但是它用于匹配精确的短语或者单词距离匹配。 - match_phrase_prefix query
match_phrase_prefix 查询像 match_phrase查询一样,但是它对最后一个单词进行了一个通配符搜索。 - multi_match query
multi_match 是match查询的多字段版本。 - common terms query
common terms 查询是一个更加特有的查询,该查询给不寻常的词更多偏好(例如 停用词)。 - query_string query
query_string 查询支持简洁的Lucene 查询字符串语法,它允许用户在包含单个* 的查询字符串中指定 AND|OR|NOT 条件和多字段搜索。该查询仅仅适用于有经验的用户。 - simple_query_string query
simple_query_string 查询是一个更加简单、更加鲁棒的query_string 语法,使用于直接暴露给用户。
2.4 Geo queries
es 支持2类geo数据,分别为geo_point 和geo_shape 2中类型;其中,gep_points 支持 lat/lon 数据对, geo_shape 支持点、线、圆、多边形和多个多边形等。
该范畴内的查询包括 geo_bounding_box查询、geo_distance查询、geo_polygon查询、geo_shape查询等4种,具体如下:
- geo_bounding_box query
geo_bounding_box 查询会匹配到在指定矩形区域内的文档。 - geo_distance query
geo_distance 查询会匹配到距某个中心点小于某个值的所有文档。 - geo_polygon query
geo_polygon 查询会匹配到在指定多边形内的所有文档。 - geo_shape query
geo_shape 查询会找到和指定geo-shape 要么相交被包含,要么不相交的文档。
具体案例见elk笔记13–Queries-geo queries
2.5 Joining queries
在像 ES 这样的分布式系统中执行全 SQL 风格的连接查询,其代价昂贵,是不可行的。作为代替,为了实现水平扩展,ES 提供了两种形式的 join。
- nested query(嵌套查询)
ES 文档中可能包含嵌套类型的字段,这些字段用来索引一些数组对象,每个对象都可以作为一条独立的文档被查询出来(用嵌套查询)。 - has_child and has_parent queries
一类父子关系可以存在单个的索引的两个类型的文档之间。
join字段关系可以存在于单个索引的文档中。其中,has_child 查询将返回其子文档能匹配特定的查询的父文档,而 has_parent 则返回其父文档能匹配特定查询的子文档。
参考 term 查询中的terms-lookup 机制,它允许用户在另一个文档的值中创建一个term 查询。
2.6 Match all query
Match all 查询是最简单的查询,它匹配所有的文档,并给它们一个相同的相关度分数1.0;其score可以通过boost参数来调整。
与之相反,Match None 请求不会匹配任何文档,其关键词为 match_none。
2.7 Span queries
Span查询是低级位置查询,可以对指定数据项的顺序和距离提供专业的控制。这些通常用于对法律文件或专利执行非常具体的查询。这些查询通常被用于试试非常特殊的查询,一般用于法律文档或者专利相关的搜索。
It is only allowed to set boost on an outer span query. Compound span queries, like span_near, only use the list of matching spans of inner span queries in order to find their own spans, which they then use to produce a score. Scores are never computed on inner span queries, which is the reason why boosts are not allowed: they only influence the way scores are computed, not spans. [不太很理解Span 查询使用场景,暂时不翻译]
除了 span_multi 查询外, span 查询不能和其它non-span类型的查询混合使用。
该范畴内的查询包括如下9种查询:
- span_containing query
Accepts a list of span queries, but only returns those spans which also match a second span query. - field_masking_span query
Allows queries like span-near or span-or across different fields. - span_first query
Accepts another span query whose matches must appear within the first N positions of the field. - span_multi query
Wraps a term, range, prefix, wildcard, regexp, or fuzzy query. - span_near query
Accepts multiple span queries whose matches must be within the specified distance of each other, and possibly in the same order. - span_not query
Wraps another span query, and excludes any documents which match that query. - span_or query
Combines multiple span queries — returns documents which match any of the specified queries. - span_term query
The equivalent of the term query but for use with other span queries. - span_within query
The result from a single span query is returned as long is its span falls within the spans returned by a list of other span queries.
2.8 Specialized queries
Specialized 类别的查询使一些专业的查询,不适合放到其它了查询类别中,当前包括如下7类:
- distance_feature query
distance_feature 查询可以根据文档字段和origin之间的距离计算相关度分数,其字段仅仅对 date, date_nanos 和 geo_point 三种类型有效。该查询可以跳过non-competitive的文档,即track_total_hits为false的时候,很多不必要的文档的score不会通过该方式计算。 - more_like_this query
more_like_this 查询可以找到和指定的文本、文档或者集合相似的文档。 - percolate query
This query finds queries that are stored as documents that match with the specified document.(不太好理解,后续再补上) - rank_feature query
rank_feature 查询可以基于文档的数字特征值来计算相关度分数,并且可以高效地避免 non-competitive 的文档。 - script query
script 查询允许通过脚本来实现一个过滤,它一般使用在过滤上下文环境中。 - script_score query
script_score 查询允许通过一个脚本来修改子查询的相关度分数。 - wrapper query
wrapper 查询可以接受其它json或者yaml字符串类型的请求,其请求体以base64的形式传给warpper的query参数。
2.9 Term-level queries
基于结构化数据中准确的值,用户可以使用term级别的查询来搜索文档。常见结构化数据包括日期范围、IP地址、价格、产品IDs等。
与全文检索不同,项级别的查询不分析查找的项,它会匹配存储在某个字段中的具体项。
term 级别的查询仍然要通过正规化属性将keyword类型的字段项标准化,更多相关细节可以参考 normalizer
term 级别的查询包括如下11 种查询:
- exists query
exists 查询用于判断指定字段是否包含写入的值 (写入的值不包含null 和[] ), 若该字段有值则返回对应的文档。 - fuzzy query
fuzzy查询指的是搜索出与特定字段的搜索项相似的文档。ES 使用 Levenshtein 编辑距离来测量相似性或模糊性。
- ids query
ids 查询基于文档的IDs返回指定的文档。 - prefix query
prefix 查询指的是特定的字段包含某个指定的前缀。 - range query
range 查询指的是特定字段在某个指定范围内,常见范围包括年龄和分数范围。 - regexp query
regexp 查询指的是特定字段匹配到指定的正则表达。 - term query
term 查询指的是匹配到指定字段中包含精确的数据项。 - terms query
terms 查询指的是匹配到指定字段中某一个精确的数据项。 - terms_set query
terms_set 查询指的是在特定字段中匹配到至少某个数量的精确数据项。用户可以通过字段或者脚本定义最少的匹配项。 - type query
type 查询返回指定类型的文档。 - wildcard query
wildcard 查询返回匹配通配符模式的文档。通配符一般都简单的通配符,例如 ki*y 匹配 以ki开头y结尾 的数据项。
2.10 minimum_should_match parameter
minimum_should_match 该参数定义的是最少应该匹配到的查询子句数量。其值最小为1,最大为实际所有查询子句数量;可以为正整数、负整数、正百分比、负百分比或者整数与百分比的组合,例如[ 3, -3, 75%,-25%, 3<95%,2<-25% 9<-3],最后一个如果为多个的组合则需要在组合之间添加一个空格。
2.11 rewrite parameter
rewrite 参数适用于有经验的用户来使用,更改这个值可以影响搜索性能和相关性。
ES 在内部使用Apache Lucene来实现写入和搜索,其原始形式是不能执行如下5中查询的:fuzzy、prefix、query_string、regexp、wildcard。
为了能执行这几类查询,Lucene 将这几种查询更改为更简单的形式,例如bool查询、bit 集合。
rewrite 参数决定来如下3个内容:
对于匹配到的每个文档,Lucene 如何计算其相关度分数;
Lucene 是否改变原始查询为bool查询或者bit 集合;
如果改变为bool查询,将包含哪些 term 查询子句。
rewrite常用的值包含如下几个:
constant_score(默认的rewrite值)
constant_score_boolean
scoring_boolean
top_terms_blended_freqs_N
top_terms_boost_N
top_terms_N
使用rewrite参数的时候,一般需要考虑其性能。大多数情况下,推荐使用 constant_score, constant_score_boolean, or top_terms_boost_N 这几种rewrite方法。
其它方法计算相关度分数时,计算代价比较昂贵,并且不能提高查询结果。
2.12 Regular expression syntax
正则表达通过占位符(运算符)在数据中进行模式匹配。它可以判断字符串中是否包含某个字串,也可以实现字串的替换,或者提取出符合条件的字串。
在ES 中,regexp 和 query_string 2种查询支持正则表达。ES 使用 Apache Lucene 的正则表达引擎来解析这些查询。
Lucene 的正则表达引擎支持所有的Unicode 字符,但是实际中值保留了如下几个操作符:
. ? + * | { } [ ] ( ) " \
若启用选择性操作符,如下几个字符也可以在正则中使用:
# @ & < > \ ~
Lucene 的正则表达引擎不支持锚操作符(anchor operators), 例如不支持 ^ (beginning of line) 和 $ (end of line。 若要匹配一个项,正则表达必须匹配完整的字符串。
3 常见查询案例
待添加
4 注意事项
es 默认返回的hits为10000个,如果需要返回全部的,则需要设置如下参数为true; “track_total_hits”: true, 也可以使用scroll api 获取所有的数据;
5 说明
- 参考文档
compound-querieselasticsearch 高手之路 - 环境说明
测试环境为es7.2.1