您的当前位置:首页正文

Elasticsearch检索分类详解

2020-08-18 来源:客趣旅游网
Elasticsearch检索分类详解

前⾔

Elasticsearch中当我们设置Mapping(分词器、字段类型)完毕后,就可以按照设定的⽅式导⼊数据。

有了数据后,我们就需要对数据进⾏检索操作。根据实际开发需要,往往我们需要⽀持包含但不限于以下类型的检索: 1)精确匹配,类似mysql中的 “=”操作;

2)模糊匹配,类似mysql中的”like %关键词% “查询操作; 3)前缀匹配; 4)通配符匹配;

5)正则表达式匹配; 6)跨索引匹配; 7)提升精读匹配。

细数⼀下,我们的痛点在于: 1)ES究竟⽀持哪些检索操作?

2)如何实现ES精确值检索、指定索引检索、全⽂检索?

这些就是本⽂着重参考ES最新官⽅⽂档,针对ES5.X版本探讨的内容。

0、检索概览

检索⼦句的⾏为取决于查询应⽤于过滤(filter)上下⽂还是查询/分析(query)上下⽂。过滤上下⽂——对应于结构化检索

1)核⼼回答的问题是:“这个⽂档是否符合这个查询条款?” 2)答案是简单的是或否,不计算分数。

3)过滤器上下⽂主要⽤于过滤结构化数据。类似于Mysql中判定某个字段是否存在: 例如:

a. 时间戳字段:是否属于2015年或2016年? b. 状态字段:是否设置为“已发布”?

经常使⽤的过滤器将被Elasticsearch**⾃动缓存,以加快性能**。分析上下⽂——对应于全⽂检索

1)核⼼回答了“本⽂档与此查询⼦句是否匹配?”的问题。

2)除了决定⽂档是否匹配之外,查询⼦句还会计算⼀个_score,表⽰⽂档与其他⽂档的匹配程度。综合应⽤场景如下:

GET /_search

{ \"query\": { \"bool\": { \"must\": [ { \"match\": { \"title\": \"Search\" }},

{ \"match\": { \"content\": \"Elasticsearch\" }} ], \"filter\": [

{ \"term\": { \"status\": \"published\" }},

{ \"range\": { \"publish_date\": { \"gte\": \"2015-01-01\" }}} ] } }}

以上检索,title中包含”Search”并且content中包含 “Elasticsearch”,status中精确匹配”published”,并且publish_date ⼤于“2015-01-01”的全部信息。以下,以“脑图”的形式直观展⽰检索分类:

以下内容的原⽂需要参考ES官⽅⽂档(随着版本变化,后续会有更新)

1、结构化检索

针对字段类型: ⽇期、时间、数字类型,以及精确的⽂本匹配。 结构化检索特点:

* 1)结构化查询,我们得到的结果 总是 ⾮是即否,要么存于集合之中,要么存在集合之外。 * 2)结构化查询不关⼼⽂件的相关度或评分;它简单的对⽂档包括或排除处理。

1.1 精确值查找

1.1.1 单个精确值查找(term query)

term 查询会查找我们指定的精确值。term 查询是简单的,它接受⼀个字段名以及我们希望查找的数值。

想要类似mysql中如下sql语句的查询操作:

SELECT document FROM products WHERE price = 20; DSL写法:

GET /my_store/products/_search{

\"query\" : { \"term\" : { \"price\" : 20 } }}

当进⾏精确值查找时, 我们会使⽤过滤器(filters)。过滤器很重要,因为它们执⾏速度⾮常快,不会计算相关度(直接跳过了整个评分阶段)⽽且很容易被缓存。如下: 使⽤ constant_score 查询以⾮评分模式来执⾏ term 查询并以⼀作为统⼀评分。GET /my_store/products/_search{

\"query\" : {

\"constant_score\" : { \"filter\" : { \"term\" : { \"price\" : 20 } } } }}

注意:5.xES中,对于字符串类型,要进⾏精确值匹配。需要讲类型设置为text和keyword两种类型。mapping设置如下:POST testindex/testtype/_mapping{

\"testtype \":{ \"properties\":{ \"title\":{

\"type\":\"text\",

\"analyzer\":\"ik_max_word\",

\"search_analyzer\":\"ik_max_word\", \"fields\":{ \"keyword\":{

\"type\":\"keyword\" } } }}}

1.1.2 布尔过滤器

⼀个 bool 过滤器由三部分组成:{

\"bool\" : {

\"must\" : [], \"should\" : [], \"must_not\" : [], \"filter\": [] }}

must ——所有的语句都 必须(must) 匹配,与 AND 等价。

must_not ——所有的语句都 不能(must not) 匹配,与 NOT 等价。 should ——⾄少有⼀个语句要匹配,与 OR 等价。 filter——必须匹配,运⾏在⾮评分&过滤模式。

就这么简单! 当我们需要多个过滤器时,只须将它们置⼊ bool 过滤器的不同部分即可。举例:

GET /my_store/products/_search{

\"query\" : { \"filtered\" : { \"filter\" : { \"bool\" : { \"should\" : [

{ \"term\" : {\"price\" : 20}},

{ \"term\" : {\"productID\" : \"XHDK-A-1293-#fJ3\"}} ],

\"must_not\" : {

\"term\" : {\"price\" : 30} } } } } }}

1.1.3 多个值精确查找(terms query)

{

\"terms\" : {

\"price\" : [20, 30] }}

如上,terms是包含的意思,包含20或者包含30。

如下实现严格意义的精确值检索, tag_count代表必须匹配的次数为1。GET /my_index/my_type/_search{

\"query\": {

\"constant_score\" : { \"filter\" : { \"bool\" : { \"must\" : [

{ \"term\" : { \"tags\" : \"search\" } }, { \"term\" : { \"tag_count\" : 1 } } ] } } } }}

1.2 范围检索(range query)

range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:gt: > ⼤于(greater than)lt: < ⼩于(less than)

gte: >= ⼤于或等于(greater than or equal to)lte: <= ⼩于或等于(less than or equal to)类似Mysql中的范围查询:

SELECT documentFROM products

WHERE price BETWEEN 20 AND 40

ES中对应的DSL如下:

GET /my_store/products/_search{

\"query\" : {

\"constant_score\" : { \"filter\" : { \"range\" : { \"price\" : { \"gte\" : 20, \"lt\" : 40 } } } } }}

1.3 存在与否检索(exist query)

mysql中,有如下sql:

SELECT tags FROM posts WHERE tags IS NOT NULL;ES中,exist查询某个字段是否存在:GET /my_index/posts/_search{

\"query\" : {

\"constant_score\" : { \"filter\" : {

\"exists\" : { \"field\" : \"tags\" } } } }}

https://blog.csdn.net/laoyang360/article/details/77623013 1.3接着往下⾯开始

因篇幅问题不能全部显示,请点此查看更多更全内容