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

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":"公路局正在治理解放大道路面积水问题"} 公,路,局,正,在,治,理,解,放,大,道,路,面,积,水,问,题

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

  • 针对要求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 } } } } } } }

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

步骤2:插入文档

POST ik_index/ik_type/3 { "title":"公路局正在治理解放大道路面积水问题" }

步骤3:实施检索

POST ik_index/ik_type/_search { "profile":"true", "query": { "match_phrase": { "title.ik_my_max":"道路" } } }

搜索结果如下: 无结果返回。

{ "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 0, "max_score": null, "hits": [] }}

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

GET /ik_index/_analyze?analyzer=ik_max_word { "text":"公路局正在治理解放大道路面积水问题" } 公路局 ,公路 ,路局 ,路 ,局正 ,正在 ,正 ,治理 ,治 ,理解 , 理 ,解放 ,解 ,放大 ,大道 ,大 ,道路 ,道 ,路面 ,路 , 面积 ,面 ,积水 ,积 ,水 ,问题

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

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

{ "token": "路面", "start_offset": 11, "end_offset": 13, "type": "CN_WORD", "position": 18 }

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

match_phrase检索时候,文档必须同时满足以下两个条件,才能被检索到: 1)分词后所有词项都出现在该字段中; 2)字段中的词项顺序要一致。 位置信息可以被存储在倒排索引中,因此 match_phrase 查询这类对词语位置敏感的查询, 就可以利用位置信息去匹配包含所有查询词项,且各词项顺序也与我们搜索指定一致的文档,中间不夹杂其他词项。

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

POST ik_index/ik_type/4 { "title":"党员干部坚持走马克思主义道路的重要性" }

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

"hits": { "total": 1, "max_score": 1.9684901, "hits": [ { "_index": "ik_index", "_type": "ik_type", "_id": "4", "_score": 1.9684901, "_source": { "title": "党员干部坚持走马克思主义道路的重要性" } } ] },

细粒度ik_max_word分词结果为:

党员干部, 党员, 干部, 坚持走, 坚持, 坚, 持, 走马, 马克思主义, 马克思, 马克, 马, 克, 思, 主义, 道路, 道, 路, 重要性, 重要, 要性, 性

构建索引的时候,道路被拆分为: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 } } } }

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

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。

原文发布于微信公众号 - 铭毅天下(gh_0475cf887cf7)

原文发表时间:2018-02-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏申龙斌的程序人生

零基础学编程024:如何快速学会SQL?

一位朋友问我如何能够较快地学会SQL,我一时还真不知道如何回答。想学会SQL(结构化查询语言),大概需要理解这些术语:数据库、关系型数据库、面向对象的数据库、键...

49570
来自专栏牛客网

阿里 & 酷家乐:实习生面试

最近海投了十家公司,暂时有阿里两面(已凉)、酷家乐两面(大概凉了)、网易一面。前两个都是基础知识发挥得还可以,两家公司二面都凉凉。 阿里一面(3.21 26mi...

56940
来自专栏大数据

快速数据管道设计:通过交换表更新各个事件决策

在 VoltDB(这是一种数据库) 经常使用到的术语,快速数据管道(Fast data pipeline),这是一种全新的现代应用程序 —— 这种应用程序将流式...

28870
来自专栏即时通讯技术

微信手机端的本地数据全文检索优化之路

基于本地数据的全文搜索(Full-Text-Search,FTS)在移动应用上扮演着重要的角色。与基于服务端提供的搜索服务不同,移动端受硬件条件限制,尤其在数据...

39620
来自专栏铭毅天下

干货 | 论Elasticsearch数据建模的重要性

数据模型是抽象描述现实世界的一种工具和方法,是通过抽象的实体及实体之间联系的形式,用图形化的形式去描述业务规则的过程,从而表示现实世界中事务的相互关系的一种映射...

39220
来自专栏牛客网

从0offer到一天谈完薪资,几乎结束秋招,前端面经回馈牛客

个人是双非渣本,没有实习经历,但是自己的项目经验巨多,之前是搞算法的,后来转向前端

25020
来自专栏牛客网

【360烤面筋】

【每日一语】生存在我们每个人体内的,一到时候,它就会抖掉身上的尘土,慢慢地萌芽开来。——《穿条纹睡衣的男孩》

7820
来自专栏北京马哥教育

MySQL入门书籍和方法分享

前言:在chinaunix上总是有很多同学咨询想学习数据库,或者是为入行DBA做些准备。几年来作为一个MySQL DBA的成长过程有一些积累和感悟,特此拿出来...

39340
来自专栏杨建荣的学习笔记

一条update语句的优化探索(r9笔记第80天)

今天经开发同学反馈,发现有一些update语句阻塞了部分业务流程,为什么说一些而不是一条,是因为这些update语句都在一个存储过程中,语句结构相仿,真有一种一...

33640
来自专栏牛客网

头条三轮面试

28100

扫码关注云+社区

领取腾讯云代金券