Elasticsearch整理笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch整理笔记相关的知识,希望对你有一定的参考价值。
es中的查询请求有两种方式,一种是简易版的查询,另外一种是使用JSON完整的请求体,叫做结构化查询(DSL)。
由于DSL查询更为直观也更为简易,所以大都使用这种方式。
DSL查询是POST过去一个json,由于post的请求是json格式的,所以存在很多灵活性,也有很多形式。
这里有一个地方注意的是官方文档里面给的例子的json结构只是一部分,并不是可以直接黏贴复制进去使用的。一般要在外面加个query为key的机构。
match
最简单的一个match例子:
查询和"我的宝马多少马力"这个查询语句匹配的文档。
|
上面的查询匹配就会进行分词,比如"宝马多少马力"会被分词为"宝马 多少 马力", 所有有关"宝马 多少 马力", 那么所有包含这三个词中的一个或多个的文档就会被搜索出来。
并且根据lucene的评分机制(TF/IDF)来进行评分。
match_phrase
比如上面一个例子,一个文档"我的保时捷马力不错"也会被搜索出来,那么想要精确匹配所有同时包含"宝马 多少 马力"的文档怎么做?就要使用 match_phrase 了
|
完全匹配可能比较严,我们会希望有个可调节因子,少匹配一个也满足,那就需要使用到slop。
|
multi_match
如果我们希望两个字段进行匹配,其中一个字段有这个文档就满足的话,使用multi_match
|
但是multi_match就涉及到匹配评分的问题了。
我们希望完全匹配的文档占的评分比较高,则需要使用best_fields
|
意思就是完全匹配"宝马 发动机"的文档评分会比较靠前,如果只匹配宝马的文档评分乘以0.3的系数
我们希望越多字段匹配的文档评分越高,就要使用most_fields
|
我们会希望这个词条的分词词汇是分配到不同字段中的,那么就使用cross_fields
|
term
term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇
|
查出的所有文档都包含"汽车保养"这个词组的词汇。
使用term要确定的是这个字段是否“被分析”(analyzed),默认的字符串是被分析的。
拿官网上的例子举例:
mapping是这样的:
PUT my_index |
PUT my_index / my_type / 1 |
其中的full_text是被分析过的,所以full_text的索引中存的就是[quick, foxes],而extra_value中存的是[Quick Foxes!]。
那下面的几个请求:
GET my_index / my_type / _search |
请求的出数据,因为完全匹配
GET my_index / my_type / _search |
请求不出数据的,因为full_text分词后的结果中没有[Quick Foxes!]这个分词。
bool查询
filter:不参与评分的快速查询
GET _search |
range:范围过滤
GET _search |
exists:字段有值
查询price有值的, null也不行 |
bool联合查询: must,should,must_not
如果我们想要请求"content中带宝马,但是tag中不带宝马"这样类似的需求,就需要用到bool联合查询。
联合查询就会使用到must,should,must_not三种关键词。
这三个可以这么理解
must: 文档必须完全匹配条件
should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
must_not: 文档必须不匹配条件
比如上面那个需求:
|
聚合查询:
filtered查询
如果你想要找到所有售价高于10000美刀的车,同时也对这些车计算其平均价格,那么可以使用一个filtered查询:
GET _search?search_type=count |
从本质上而言,使用filtered查询和使用match查询并无区别,正如我们在上一章所讨论的那样。该查询(包含了一个过滤器)返回文档的一个特定子集,然后聚合工作在该子集上。
过滤桶(Filter Bucket)
如果你只想过滤聚合结果呢?假设我们正在创建针对汽车交易的搜索页面,我们想要根据用户搜索内容来展示对应结果。但是我们也想通过包含上个月出售的汽车的平均价格(匹配搜索的汽车)来让页面更加丰富。
此时我们不能使用简单的作用域,因为有两个不同搜索条件。搜索结果必须要匹配ford,但是聚合结果必须要匹配ford以及售出时间为上个月。
为了解决这一问题,我们使用一个名为filter的特殊桶。通过制定一个过滤器,当文档匹配了该过滤器的规则时,它就会被添加到桶中。
以下是得到的查询:
GET _search?search_type=count |
因为过滤器桶和任何其它桶以相似的方式工作,你可以任意地将其它桶和指标包含在其中。所有的嵌套组建都会”继承”该过滤器。从而使你能够根据需要对聚合中的内容进行过滤。
后置过滤器(Post Filter)
目前,我们有了用于过滤搜索结果和聚合的过滤器(filtered查询),也有了用于过滤聚合中某一部分的过滤器(filter桶)。
你也许会好奇,“是否有一种过滤器只过滤搜索结果,而不过滤聚合呢?”这个问题的答案就是使用post_filter。
它是搜索请求内能够接受一个过滤器作为参数的顶层元素。该过滤器会在查询执行完毕后生效(后置因此得名:在查询执行之后运行)。正因为它在查询执行后才会运行,所以它并不会影响查询作用域 - 因此就不会对聚合有所影响。
我们可以利用这一行为在搜索条件中添加额外的过滤器,而不影响用户界面中类似于类别分面(Categorical Facets)的元素。让我们设计另一个针对汽车交易的搜索页面。该页面允许用户对汽车进行搜索,同时还能够根据颜色进行过滤。颜色通过聚合提供:
GET _search?search_type=count |
post_filter元素是一个顶层元素,只会对搜索结果进行过滤。
查询部分呢用来找到所有ford汽车。然后我们根据一个terms聚合来得到颜色列表。因为聚合是在查询作用域中进行的,得到的颜色列表会反映出ford汽车的各种颜色。
最后,post_filter会对搜索结果进行过滤,只显示绿色的ford汽车。这一步发生在执行查询之后,因此聚合是不会被影响的。
这一点对于维持一致的用户界面而言是非常重要的。假设一个用户在界面上点击了一个分类(比如,绿色)。期望的结果是搜索结果被过滤了,而用户界面上的分类选项是不会变化的。如果你使用了一个filtered查询,用户界面上也立即会对分类进行更新,此时绿色就变成了唯一的选项 - 这显然不是用户想要的!
只有当你需要对搜索结果和聚合使用不同的过滤方式时才考虑使用post_filter。有时一些用户会直接在常规搜索中使用post_filter。
不要这样做!post_filter会在查询之后才会被执行,因此会失去过滤在性能上帮助(比如缓存)。
post_filter应该只和聚合一起使用,并且仅当你使用了不同的过滤条件时。
选择合适类型的过滤 - 搜索结果(Search Hits),聚合(Aggregations),或两者 - 通常都取决于你的用户界面的行为。过滤器的选择(或者组合)取决于你想要如何向用户展示结果数据。
A filtered query affects both search results and aggregations.filtered查询会影响搜索结果和聚合。
filter桶只影响聚合。
post_filter只影响搜索结果。
关于排序、分页查询
GET _search |
以上是关于Elasticsearch整理笔记的主要内容,如果未能解决你的问题,请参考以下文章
ElasticSearch笔记整理:Java API使用与ES中文分词
区块链技术与应用肖臻老师笔记整理之------17-ETH-交易树和收据树