Elasticsearch基础查询表达式
查询表达式
查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。
要使用这种查询表达式,只需将查询语句传递给 query 参数:GET /_search { "query": YOUR_QUERY_HERE }
空查询(empty search) — {} — 在功能上等价于使用 match_all 查询, 正如其名字一样,匹配所有文档:GET /_search { "query": { "match_all": {} } }
拷贝为 curl在 Sense 中查看查询语句的结构
一个查询语句的典型结构: { QUERY_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } }
如果是针对某个字段,那么它的结构如下:{ QUERY_NAME: { FIELD_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } }
举个例子,你可以使用 match 查询语句 来查询 tweet 字段中包含 elasticsearch 的 tweet:{ "match": { "tweet": "elasticsearch" } }
完整的查询请求如下:GET /_search { "query": { "match": { "tweet": "elasticsearch" } } }合并查询语句
查询语句(Query clauses) 就像一些简单的组合块,这些组合块可以彼此之间合并组成更复杂的查询。这些语句可以是如下形式: 叶子语句(Leaf clauses) (就像 match 语句) 被用于将查询字符串和一个字段(或者多个字段)对比。复合(Compound) 语句 主要用于 合并其它查询语句。 比如,一个 bool 语句 允许在你需要的时候组合其它语句,无论是 must 匹配、 must_not 匹配还是 should 匹配,同时它可以包含不评分的过滤器(filters):{ "bool": { "must": { "match": { "tweet": "elasticsearch" }}, "must_not": { "match": { "name": "mary" }}, "should": { "match": { "tweet": "full text" }}, "filter": { "range": { "age" : { "gt" : 30 }} } } }
一条复合语句可以合并 任何 其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。
例如,以下查询是为了找出信件正文包含 business opportunity 的星标邮件,或者在收件箱正文包含 business opportunity 的非垃圾邮件:{ "bool": { "must": { "match": { "email": "business opportunity" }}, "should": [ { "match": { "starred": true }}, { "bool": { "must": { "match": { "folder": "inbox" }}, "must_not": { "match": { "spam": true }} }} ], "minimum_should_match": 1 } }查询与过滤
Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)。
当使用于 过滤情况 时,查询被设置成一个"不评分"或者"过滤"查询。即,这个查询只是简单的问一个问题:"这篇文档是否匹配?"。回答也是非常的简单,yes 或者 no ,二者必居其一。 created 时间是否在 2013 与 2014 这个区间?status 字段是否包含 published 这个单词?lat_lon 字段表示的位置是否在指定点的 10km 范围内?
当使用于 查询情况 时,查询就变成了一个"评分"的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好 (匹配程度如何)。 此查询的典型用法是用于查找以下文档: 查找与 full text search 这个词语最佳匹配的文档包含 run 这个词,也能匹配 runs 、 running 、 jog 或者 sprint 包含 quick 、 brown 和 fox 这几个词 — 词之间离的越近,文档相关性越高标有 lucene 、 search 或者 java 标签 — 标签越多,相关性越高
一个评分查询计算每一个文档与此查询的 相关程度 ,同时将这个相关程度分配给表示相关性的字段 _score ,并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 "正确" 的答案。
自 Elasticsearch 问世以来,查询与过滤(queries and filters)就独自成为 Elasticsearch 的组件。但从 Elasticsearch 2.0 开始,过滤(filters)已经从技术上被排除了,同时所有的查询(queries)拥有变成不评分查询的能力。
然而,为了明确和简单,我们用 "filter" 这个词表示不评分、只过滤情况下的查询。你可以把 "filter" 、 "filtering query" 和 "non-scoring query" 这几个词视为相同的。
相似的,如果单独地不加任何修饰词地使用 "query" 这个词,我们指的是 "scoring query" 。 性能差异
过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快。考虑到至少有一个过滤查询(filtering query)的结果是 "稀少的"(很少匹配的文档),并且经常使用不评分查询(non-scoring queries),结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。
相反,评分查询(scoring queries)不仅仅要找出匹配的文档,还要计算每个匹配文档的相关性,计算相关性使得它们比不评分查询费力的多。同时,查询结果并不缓存。
多亏倒排索引(inverted index),一个简单的评分查询在匹配少量文档时可能与一个涵盖百万文档的filter表现的一样好,甚至会更好。但是在一般情况下,一个filter 会比一个评分的query性能更优异,并且每次都表现的很稳定。
过滤(filtering)的目标是减少那些需要通过评分查询(scoring queries)进行检查的文档。 如何选择查询与过滤
通常的规则是,使用查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(filters)。