ES使用Query DSL语言定义查询语句,查询语句分为两个类型:子查询语句、复合查询语句
子查询语句:查询特定字段的特定值,比如match查询、term查询、range查询
复合查询语句:可以组合多个子查询或复合查询语句,来实现特定的逻辑查询,比如 bool查询、dis_max查询、constant_score查询
ES查询语句分上面两种,查询语境也分两种,分别是查询(query context)、过滤(filter context)
查询:查询是用来回答“How well does this document match this query clause?”,就是会计算相关性,从而给出一个文档的匹配程度(_score)。
过滤:过滤是用来回答“does this document match this query clause?”,答案就只有Yes or No两种,就是要么匹配,要么不匹配。
查询语句的效果,要看查询语句是在query context中执行,还是在filter context中执行;
查询语句有子查询和复合查询,从具体的查询语句实现上看,可以大体分为八类:
1. Match All Query :
2. Full text queries
3. term level queries
4. compound queries
5. joining queries
6. geo queries
7. specialized queries
8. span queries
最简单的查询语句,将匹配所有的文档,并给所有的文档赋_score为1.0
Match Query
match query 属于全文查询,全文查询的特点是,可以进行相似度查询,也可以进行精确值查询,参见解释:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/term-vs-full-text.html
match查询,按我理解,就是先判断是否对查询内容进行analysis,判断依据是存储时,这个field是否有analysis;如果不需要analysis,那么就转变成了term查询;如果需要analysis,那么就是analysis成多个词项,然后转成terms查询,将查询结果根据规则,进行评分;
https://www.elastic.co/guide/cn/elasticsearch/guide/current/match-query.html
https://www.elastic.co/guide/cn/elasticsearch/guide/current/match-multi-word.html
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_how_match_uses_bool.html
(根据上面2/3链接,match查询需要analysis时,是转成多个term查询,然后用bool查询组合,然后评分)
备注:
(1)match查询时,会先看查询的field,在存储时,是否被analysis:如果被analysis,那么查询前,会先对查询的内容进行analysis;否则,将查询的内容作为一个单一的词项,此时就是精确值查询;这就是全文索引,可以相似度查询,也可以精确值查询;
(2)match查询时,可以控制operator操作符,比如,查询“BROWN DOG ”,默认操作符是“or”,就是包含BROWN 或 DOG 的,都会被搜索出来;而如果指定操作符是“and”,那么{"title": "The quick brown fox"}这个结果就不会被查询到,因为这个结果中,不包含dog;{"title": "The quick brown fox jumps over the quick dog"}这个可以查出来,虽然brown 和 dog不在一块;
(3)在备注2中,大眼一看,感觉很合适,但是,想想,如果一个查询内容,被分成了10个词项,那么,用or,匹配上10个中的任何一个,和用and,匹配上所有的10个,是不是感觉有点非黑即白的过于绝对感,match查询提供了minimum_should_match,可以控制至少匹配上多少个词项,更灵活一点。
(4)在备注3中,感觉是更好了一点,不过有个明显的问题,查询内容会被分解为多少个词项,是不确定的,因为每次我们查询的内容又不一样,每次都计算下会有多少词项?这里minimum_should_match支持百分数的表示方法,如,设置为75%,如果查询内容有四个词项,则至少匹配上三个,如果只有三个词项,75%会被es自动解析成66.6%,即三个词里至少匹配两个;
Match Phrase Query
match phrase query是短语查询,可以通过match query
https://www.elastic.co/guide/en/elasticsearch/reference/6.2/term-level-queries.html
term
query
term query 属于过滤器查询,可以处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。
备注:
(1)当我们使用term查询文本“XHDK-A-1293-#fJ3”时,会查找不到,这不是es错误,而是因为我们存储“XHDK-A-1293-#fJ3”时,使用了分析器,将“XHDK-A-1293-#fJ3”拆分为了“XHDK”、“A”、“1293”、“fJ3”四个字段,而使用term查询时,是不使用分析器的,所以是查询不到的;所以term查询文本时,一般是对词项进行查询;另外,即使只是大小写不同,也是查询不到的,
(2)如果想要查询多个精确值(数字、布尔值、日期、文本),比如,想查询价格为20或30的,我们不必使用两个term查询,只需要使用一个terms查询即可({"terms" : {"price" : [20, 30]}}),terms查询可以看着term查询的复数形式,会将价格为20的 和价格为30 的全部查出来;
(3)term和terms查询,是包含,而不是等于,如:要查询{ "term" : { "tags" : "search" } },会将
{ "tags" : ["search"] }和{ "tags" : ["search", "open_source"] } 都查询出来,而不是只查询出第一个;
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_finding_exact_values.html
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_finding_multiple_exact_values.html
Range Query
range query属于过滤器查询,是范围查询,有时候,范围查询比精确值查询更有用,比如我想知道价格在20到40之间的商品;
range query可以处理数字(numbers)、日期(dates)以及字符串,不过字符串还是不要用范围查询的好,效率会很低;
对数字取范围没啥好说的, 就大于、大于等于、小于、小于等于四个符号加数字就可以;
对于日期,es支持设置要匹配的日期格式,还可以对日期进行计算,比如,想查找过去一小时内的文档,可以用"range" : { "timestamp" : { "gt" : "now-1h" }},其中now表示当前时间,而"now-1h"就是对es支持的对日期的计算
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_ranges.html
https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-date-format.html
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_finding_exact_values.html
https://www.elastic.co/guide/en/elasticsearch/reference/6.2/query-dsl-term-query.html 最后一个例子
https://www.elastic.co/guide/en/elasticsearch/reference/6.2/common-options.html#common-options-error-options