对于 ES,当我们了解了 mapping 和 analysis 的相关内容之后,使用者更关心的问题往往是如何构建查询语句从而搜索到自己想要的数据。因此,本文将会介绍 Query DSL 的相关内容。
一
Query DSL
Query DSL 是什么?
Query Domain Specific Language ,特定领域查询语言。首先它的作用是查询,其次其语法格式只能作用于 ES 中,所以就成了所谓的特定领域。
Query DSL 可分为两种类型:
1. Leaf query clauses
简单查询子句,查询特定 field 字段中的特定值。
2. Compound query clauses
复合查询子句,由多个简单查询子句或复合查询子句以逻辑方式组合而成。
二
Query and filter context
查询语句的行为依赖于其上下文环境是 query context 还是 filter context 。
1. Filter context :
某个 document 文档是否匹配查询语句,答案只有是和否。对于 filter 查询 ES 会自动进行缓存处理,因此查询效率非常高,应尽可能多的使用。
2. Query context :
除了文档是否匹配之外,还会计算其匹配程度,以 _score 表示。例如某个文档被 analyzer 解析成了十个 terms,而查询语句匹配了其中的七个 terms,那么匹配程度 _score 就是 0.7 。
三
Match All Query
最简单的查询。
match_all : 匹配所有文档。
match_none : 不匹配任何文档。
四
Full text queries
全文查询,在执行之前会先分析进行查询的字符串,而查询的行为也与 analyzer 息息相关。
位于这一组内的查询包括:
01
match
全文查询中的标准查询,包括模糊匹配和短语或邻近查询。
02
match_phrase
类似于 match ,但用于匹配精确短语或单词邻近匹配。
03
match_phrase_prefix
类似于 match_phrase,但是进行单词尾部通配符搜索。
04
multi_match
match 的 multi-fields 多字段版本。
05
common terms
优先考虑不常见单词的更专业的查询。例如英文中的 the 是一个常见的高频单词,若直接查询会匹配到大量文档且浪费性能,但是某些时候又无法直接将其忽略,这时候就用到了 common terms query ,其原理是先匹配低频单词,然后在此匹配结果上再去匹配 the 这种高频单词。
06
query_string
支持 Lucene 查询字符串语法,对 Lucene 比较熟悉的可以玩玩,但一般不需要用到。
07
simple_query_string
query_string 的简易版本。
五
Term level queries
term 是倒排索引中的基本单元,term-level 级别的查询也是直接操作精确的存储在倒排索引上的 terms 。通常用于结构化数据查询,如数字、日期、枚举,而不是全文字段。
查询包括:
01
term
精确匹配某个 term 。
02
terms
匹配多个 terms 中的任意一个。
03
terms_set
版本 6.1 才加入的查询。匹配一个或多个 terms,minimum should match 指定至少需要匹配的个数。
04
range
范围查询。
05
exists
存在与否。判断依据是 non-null 非空值。若要查询不存在,则可以使用 must_not 加 exists 。
06
prefix
字段头部确定,尾部模糊匹配。
07
wildcard
通配符模糊匹配。符号 ?匹配一个字符,符号 * 匹配任意字符。
08
regexp
正则匹配。
09
fuzzy
模糊相似。模糊度是以 Levenshtein edit distance 来衡量,可以理解为为了使两个字符串相等需要更改的字符的数量。
10
type
指定 type 。
11
ids
指定 type 和文档 ids 。
六
Compound queries
复合查询由其它复合查询或简单查询组成,其要么组合他们的查询结果和匹配分数,更改查询行为,要么从 query 切换到 filter context 。
查询包括:
01
constant_score
包裹 query 查询,但在 filter context 中执行,所有匹配到的文档都被给与一个相同的 _score 分数。
02
bool
组合多个查询,如 must 、should、must_not、filter 语句。must 和 should 有 scores 分数的整合,越匹配分数越高,must_not 和 filter 子句执行于 filter context 中。
03
dis_max
匹配多个查询子句中的任意一个,与 bool 从所有匹配的查询中整合匹配分数不同的是,dis_max 只会选取一个最匹配的查询中的分数。
04
function_score
使用特定函数修改主查询返回的匹配分数。
05
boosting
匹配正相关的查询,同时降低负相关查询的匹配分数。
七
Joining queries
在 ES 这种分布式系统中执行完整 SQL 风格的 join 连接的代价是非常昂贵的,而作为替代并有利于水平扩展 ES 提供了以下两种方式:
01
nested
针对包含有 nested 类型的 fields 字段的文档,这些 nested 字段被用于索引对象数组,而其中的每个对象都可以被当做一个独立的文档以供查询。
02
has_child、has_parent
join 连接关系可能存在于同一个索引中不同 document 文档之间。
has_child 查询返回 child 子文档匹配的 parent 父文档。
has_parent 查询返回 parent 父文档匹配的 child 子文档。
03
parent Id
直接指定父文档的 ID 进行查询。
八
Geo queries
ES 提供了两种类型的 geo 地理数据:
geo_point:lat / lon 纬度/经度对。
geo_shape:地理区间,包括 points 点组、lines 线、circles 圆形区域、polygons 多边形区域、multi-polygons 复合多边形区域。
查询包括:
01
geo_shape
查询指定的地理区间。要么相交、要么包含、要么不相交。查的是 geo_shape 。
02
geo_bounding_box
查询指定矩形地理区间内的坐标点。查的是 geo_points 。
03
geo_distance
查询距离某个中心点指定范围内点,也就是一个圆形区间。查的是 geo_points 。
04
geo_polygon
查询指定多边形区间内的点。查的是 geo_points 。
九
Specialized queries
未包含于其它查询组内的查询:
01
more_like_this
相似于指定的 text 文本、document 文档、或 documents 文档集。
这里的相似,不仅仅是指 term 的具体内容,同时也要考量其位置因素。查询字段必须先存储 term_vector 也就是 term 向量。
02
script
接受一个 script 作为一个 filter 。
03
percolate
通常情况下,我们通过 query 语句去查询具体的文档,但是 percolate 正好相反,它是通过文档去查询 query 语句( query 必须先注册到 percolate 中)。
percolate 一般常用于数据分类、数据路由、事件监控和预警。
04
wrapper
接受 json 或 yaml 字符串进行查询,需要 base64 编码。
十
Span queries
更加底层的查询,对 term 的顺序和接近度有更加严格的要求,常用于法律或专利文件等。
除了 span_multi 之外,其它的 span 查询不能与非 span 查询混合使用。
此类所有查询在 Lucene 中都有对应的查询。
01
span_term
与 term query 相同,但用于其它 span queries 中,因为不能混合使用的原因才有的这个 span 环境特定的查询。
02
span_multi
包裹 term、range、prefix、wildcard、regexp、fuzzy 查询,以在 span 环境下使用。对应于 Lucene 中的 SpanTermQuery 。
03
span_first
相对于起始位置的偏移距离。对应于 Lucene 中的 SpanFirstQuery 。
04
span_near
匹配必须在多个 span_term 的指定距离内,通常用于检索某些相邻的单词。对应于 Lucene 中的 SpanNearQuery 。
05
span_or
匹配多个 span queries 中的任意一个。对应于 Lucene 中的 SpanOrQuery 。
06
span_not
不匹配,也就是排除。对应于 Lucene 中的 SpanNotQuery 。
07
span_containing
指定多个 span queries 中的匹配优先级。对应于 Lucene 中的 SpanContainingQuery 。
08
span_within
与 span_containing 类似,但对应于 Lucene 中的 SpanWithinQuery 。
09
field_masking_span
对不同的 fields 字段执行 span-near 或 span-or 查询。
Query DSL 部分的内容大概就是这么多,本文只是让你对于查询部分有一个整体的大概的印象,至于某个具体查询的详细细节还请查阅官方文档。