Elasticsearch实战 | match_phrase搜不出来,怎么办?

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、问题抛出某个词组在Elasitcsearch中的某个document中存在,就一定通过某种匹配方式把它搜出来。举例:

title=公路局正在治理解放大道路面积水问题。


输入关键词:道路,能否搜索到这个document呢?

实际应用中可能需要:

1)检索关键词”理解”、”解放”、”道路”、“理解放大”,都能搜出这篇文档。

2)单个的字拆分“治”、“水”太多干扰,不要被检索出来。

3)待检索的词不在词典中,也必须要查到。

4)待检索词只要在原文title或content中出现,都要检索到。

5)检索要快,要摒弃wildcard模糊匹配性能问题。


2、问题分析

常用的stand标准分词,可以满足要求1)、3)、4)、5)。

标准分词器是什么鬼?

标准分析仪是默认分析仪,如果没有指定,则默认使用该分词器。 它提供了基于语法的标记,并且适用于大多数语言。

对于中文字符串,会逐个汉字分词。

标准分词器的结果如下:


GET /ik_index/_analyze?analyzer=standard

{

"text":"公路局正在治理解放大道路面积水问题"

}

公,路,局,正,在,治,理,解,放,大,道,路,面,积,水,问,题

1

2

3

4

5

但,会出现冗余数据非常多。

针对要求2),排除match检索,排除stand分词。

针对要求5),排除wildcard模糊检索。

针对要求3)、4),新词也要被检索到比如:“声临其境”、“孙大剩”等也要能被搜索到。

针对要求1),采用match_phrase貌似靠谱些。


3、小试牛刀

先使用IK-max-word细粒度分词器,结合match_phrase试一试?


步骤1:定义索引和Mapping

PUT ik_index

{

 "mappings":{

 "ik_type":{

 "properties":{

 "title":{

 "type":"text",

 "fields":{

 "ik_my_max":{

 "type":"text",

 "analyzer":"ik_max_word"

 },

 "ik_my_smart":{

 "type":"text",

 "analyzer":"ik_smart"

 },

 "keyword":{

 "type":"keyword",

 "ignore_above":256

 }

 }

 }

 }

 }

 }

 }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

这里,为了验证分词,同时使用了ik_smart和ik_max两种分词。

实际开发中不需要,因为:两种分词共存,会导致导入数据创建索引的时候,索引会非常大,对磁盘和检索性能都会有影响。


步骤2:插入文档

POST ik_index/ik_type/3

{

 "title":"公路局正在治理解放大道路面积水问题"

}

1

2

3

4

步骤3:实施检索

POST ik_index/ik_type/_search

{

 "profile":"true",

 "query":

 {

 "match_phrase":

 {

 "title.ik_my_max":"道路"

 }

 }

}

1

2

3

4

5

6

7

8

9

10

11

搜索结果如下:

无结果返回。


{

 "took": 1,

 "timed_out": false,

 "_shards": {

 "total": 5,

 "successful": 5,

 "failed": 0

 },

 "hits": {

 "total": 0,

 "max_score": null,

 "hits": []

 }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

为什么使用了max_word细粒度分词,使用了match_pharse检索,为什么没有结果。

分析一下:

细粒度ik_max_word分词结果为:


GET /ik_index/_analyze?analyzer=ik_max_word

{

"text":"公路局正在治理解放大道路面积水问题"

}

公路局 ,公路 ,路局 ,路 ,局正 ,正在 ,正 ,治理 ,治 ,理解 ,

理 ,解放 ,解 ,放大 ,大道 ,大 ,道路 ,道 ,路面 ,路 ,

面积 ,面 ,积水 ,积 ,水 ,问题

1

2

3

4

5

6

7

以上方式,除了可以返回分词结果外,还能返回词所在的位置position。


构建索引的时候,道路被拆分为:道路:16,道:17,路:19。(注意中间加了18:路面)


{

 "token": "路面",

 "start_offset": 11,

 "end_offset": 13,

 "type": "CN_WORD",

 "position": 18

 }

1

2

3

4

5

6

7

而检索的时候,而道路拆分为: 道路0 道1 路2


match_phrase检索时候,文档必须同时满足以下两个条件,才能被检索到:

1)分词后所有词项都出现在该字段中;

2)字段中的词项顺序要一致。

位置信息可以被存储在倒排索引中,因此 match_phrase 查询这类对词语位置敏感的查询, 就可以利用位置信息去匹配包含所有查询词项,且各词项顺序也与我们搜索指定一致的文档,中间不夹杂其他词项。


为了验证如上的解释,新增一篇“道路”相关的title,检验一下:


POST ik_index/ik_type/4

{

 "title":"党员干部坚持走马克思主义道路的重要性"

}

1

2

3

4

注意:这时,搜索道路是可以匹配到的。


 "hits": {

 "total": 1,

 "max_score": 1.9684901,

 "hits": [

 {

 "_index": "ik_index",

 "_type": "ik_type",

 "_id": "4",

 "_score": 1.9684901,

 "_source": {

 "title": "党员干部坚持走马克思主义道路的重要性"

 }

 }

 ]

 },

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

细粒度ik_max_word分词结果为:


党员干部, 党员, 干部, 坚持走, 坚持, 坚, 持, 走马, 马克思主义, 马克思,

马克, 马, 克, 思, 主义, 道路, 道, 路, 重要性, 重要,

要性, 性

1

2

3

构建索引的时候,道路被拆分为:15,16,17位置。

与检索的词项顺序是一致的。

这里解析更详细:http://t.cn/R8pzw9e


4、match_pharse都搜不出来,还有没有别的方案?

有,和match_pharse类似,不过match_phrase_prefix支持最后一个term前缀匹配。

除了把查询文本的最后一个分词只做前缀匹配之外,match_phrase_prefix和match_phrase查询基本一样,参数 max_expansions 控制最后一个单词会被重写成多少个前缀,也就是,控制前缀扩展成分词的数量,默认值是50(官网文档建议50)。

扩展的前缀数量越多,找到的文档数量就越多;

如果前缀扩展的数量太少,可能查找不到相应的文档,遗漏数据。


POST ik_index/ik_type/_search

{

 "profile":"true",

 "query":

 {

 "match_phrase_prefix" : {

 "title.ik_my_max" : {

 "query": "道路",

 "max_expansions": 50

 }

 }

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

经验证: 关键词”理解”、”解放”、”道路”、“理解放大”,都能搜出这篇文档。


5、应用场景

我们自己开发搜索引擎的时候,经常会出现基于title或者content字段进行检索。

如果用match检索,会出现噪音很多的情况;

如果用match_phrase,会出现某些字段检索不出来的情况,如上分析的“道路”;

如果用wildcard,能检索出来,但又有性能问题的存在。

这时候,可以考虑下: match_phrase_prefix。


6、小结

实际开发中,根据应用场景不同,采用不同的分词器。

如果选用ik,建议使用ik_max_word分词,因为:ik_max_word的分词结果包含ik_smart。

匹配的时候,如果想尽可能的多检索结果,考虑使用match;

如果想尽可能精确的匹配分词结果,考虑使用match_phrase;

如果短语匹配的时候,怕遗漏,考虑使用match_phrase_prefix。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
7月前
|
存储 数据采集 数据处理
数据处理神器Elasticsearch_Pipeline:原理、配置与实战指南
数据处理神器Elasticsearch_Pipeline:原理、配置与实战指南
292 12
|
8月前
|
缓存 数据处理 数据安全/隐私保护
Elasticsearch索引状态管理实战指南
Elasticsearch索引状态管理实战指南
105 0
|
8月前
|
存储 索引
Elasticsearch索引之嵌套类型:深度剖析与实战应用
Elasticsearch索引之嵌套类型:深度剖析与实战应用
|
9月前
|
人工智能 自然语言处理 开发者
Langchain 与 Elasticsearch:创新数据检索的融合实战
Langchain 与 Elasticsearch:创新数据检索的融合实战
288 10
|
8月前
|
存储 JSON 搜索推荐
Springboot2.x整合ElasticSearch7.x实战(三)
Springboot2.x整合ElasticSearch7.x实战(三)
63 0
|
8月前
|
存储 自然语言处理 关系型数据库
Springboot2.x整合ElasticSearch7.x实战(二)
Springboot2.x整合ElasticSearch7.x实战(二)
61 0
|
8月前
|
搜索推荐 数据可视化 Java
Springboot2.x整合ElasticSearch7.x实战(一)
Springboot2.x整合ElasticSearch7.x实战(一)
67 0
|
9月前
|
自然语言处理 测试技术 网络安全
ElasticSearch7最新实战文档-附带logstash同步方案
ElasticSearch7最新实战文档-附带logstash同步方案
137 0
|
9月前
|
canal 自然语言处理 关系型数据库
Elasticsearch 线上实战问题及解决方案探讨
Elasticsearch 线上实战问题及解决方案探讨
76 0
|
9月前
|
监控 API 索引
实战问题:Elasticsearch 2.X 数据如何迁移到 7.X?
实战问题:Elasticsearch 2.X 数据如何迁移到 7.X?
64 0

热门文章

最新文章