[版权声明]:本文章由danvid发布于http://danvid.cnblogs.com/,如需转载或部分使用请注明出处

在业务中经常会遇到类似数据库的"like"的模糊匹配需求,而es基于分词的全文检索也是有类似的功能,这个就是短语匹配match_phrase,但往往业务需求都不是那么简单,他想要有like的功能,又要允许有一定的容错(就是我搜索"东方宾馆"时,"广州花园宾馆酒店"也要出来,这个就不是单纯的"like"),下面就是我需要解析的问题(在此吐槽一下业务就是这么变态。。)

描述一个问题时首先需要描述业务场景:假设es中有一索引字段name存储有以下文本信息:

doc[1]:{"name":"广州东方宾馆酒店"}

doc[2]:{"name":"广州花园宾馆酒店"}

doc[3]:{"name":"东方公园宾馆"}

需求要求在输入:"东方宾馆"的时候doc[1]排最前面doc[3]排第二doc[2]排第三,对于这个需求从简单的全文检索match来说,doc[3]:{"name":"东方公园宾馆"}应该是第一位(注意:为了简化原理分析,分词我们使用standard即按单个字分词)

业务分析:显然对于上面的业务场景如果单独使用match的话,显然是不合适,因为按照standard分词,doc[3]的词条长度要比doc[1]的词条长度短,而词频又是都出现了[东][方][宾][馆]4个词,使用match匹配的话就会吧doc[3]排到最前面,显然业务希望把输入的文字顺序匹配度最高的数据排前面,因为我确实要找的是"广州东方宾馆酒店"而不是"东方公园宾馆"你不能把doc[3]给我排前面,OK业务逻辑好像是对的那么怎么解决问题;

解决问题前介绍一哈match_phrase原理(match的原理我就不说了自己回去看文档),简单点说match_phrase就是高级"like"。api如下:

GET test_index/_search

{"query": {"match_phrase": {"message": {"query" : "东方宾馆","slop" : 2}

}

}

}

es在给文本分词的时候,除了分词之外还有一个词条标记,就是position,例如我按照standard对以上三个doc的name进行分词会变成这样:

doc[1]:广[0],州[1],东[2],方[3],宾[4],馆[5],酒[6],店[7];

doc[2]:广[0],州[1],花[2],园[3],宾[4],馆[5],酒[6],店[7];

doc[3]:东[0],方[1],公[2],园[3],宾[4],馆[5];

query文本分词:东[0],方[1],宾[2],馆[3];

使用match_phrase时:

1.es会先过滤掉不符合的query条件的doc,即doc[2]中没有"东方"两个词汇,会被过滤掉

2.es会根据分词的position对分词进行过滤和评分,这个是就slop参数,默认是0,意思是查询分词只需要经过距离为0的转换就可以变成跟doc一样的文档数据,例如:对于doc[1]来说slop就是0了,对于doc[3]slop就是2,即"宾"和"馆"最大位移这两个分词只需要最多移动2个位置就可以变成"东方宾馆"(反过来也一样,query的文本中的"宾"和"馆"只需要移动2个位置就可以变成"东方**宾馆"),用数学的理解就是doc[3]的宾[4]-东[0]=4,query文本中的宾[2]-东[0]=2,那么转换距离slop就是4-2=2,同理doc[3]的馆[5]-东[0]=5,query的是3,slop结果也是2,那么"宾"和"馆"最大的slop就是2,则query时设置slop等于2就能把doc[3]匹配出来,当设置为0时就是我们数据库的"like"

原理解析完了,就知道使用match只能匹配相关度即tf/idf,而分词之间的位置关系却无法保证,而match_phrase能保证分词间的邻近关系,那么就可以利用两者优势,结合搜索进行评分

GET test_index/_search

{"query": {"bool": {"must": {"match": {"name": {"query": "东方宾馆"}

}

},"should": {"match_phrase": {"name": {"query": "东方宾馆","slop": 0}

}

}

}

}

}

这样就的结果就是相当于match_phrase帮match进行了相关度分数的加分,当然你也可以通过修改slop的参数来进行步控制分数,这个就根据用户需求来了;

性能问题:其实使用match_phrase性能是要比单纯的全文检索性能低的,因为他要计算位置嘛,那么想提高性能可以通过先使用match进行过滤数据,然后利用rescore api对已经match的结果进行加分,这样就减少了部分不必要的非match过滤:

GET test_index/_search

{"query": {"match": {"name":"东方宾馆"}

}, "rescore": {"window_size": 30,"query": {"rescore_query": {"match_phrase": {"name": {"query": "东方宾馆","slop": 0}

}

}

}

}

}

#window_size 是每一分片进行重新评分的顶部文档数量这个只要大于你可能分页的总数*每页的数量即可(pageNumber*pageSize)实际上不需要这么多因为翻页不可能很深,这个根据业务调整即可。

总结及注意点:

1.rescore其实跟bool结合一样是评分的相加,评分不在这里细说了;

2.虽然可以提高相关度评分,但是还是存在可能match很低+一个很低的match_phrase结果没有单独只匹配了一个match的分数高的情况,但是这是很极限了,也是符合相关度评分原理的;

3.由于match_phrase是在搜索阶段进行的计算,会影响搜索效率,据说比term查询慢20倍,所以不要进行大文本量的字段搜索,尽量进行标题,名字这种类型的搜索才使用这个;

4.本文章没有讨论在文本数据重复时的情况,即文本中有多个"[东][方][宾][馆]"和query文本中有多个"[东][方][宾][馆]"分词的情况,但是原理是一样的还是取距离转换的最小值;

5.文中使用了standard分词,实际上可能会用不同的分词器,但是建议使用match_phrase时使用标准的一个个分词,这样是方便进行邻近搜索的控制的,如果使用ik等分词,执行match_phrase时分词是不可控的,所以结果也是不可控。match使用ik,match_phrase用standard结合一起使用也是可以的;

6.邻近搜索效率较低,其实可以通过增加词库的方式进行单纯使用match匹配效率是最高的,前提是你知道客户会搜索什么,这又是另一个研究话题了

更新[2019-05-22]:

补充:短语匹配match_phrase必须要满足下面的要求才能认定和["东方宾馆"]这个词条匹配(以standard分析器为例)

1.搜索的词必须有且仅有["东","方","宾","馆"]这几个词(对于中文是字)的一个或者多个,如果有其他的词(对于中文是字)是不会匹配到的,slop不是完全等同于莱文斯坦距离,可以理解成字符的偏移

2.查询词中偏移量应该跟文档中词的偏移量一样,或者在slop的偏差范围内,就是上文解析的意思。

这里讲解一下fuzzy和match_phrase的区别

1.fuzzy是词/项级别的模糊匹配,match_phrase是基于短语级别的

例如对于英文(standard分析器)来说"dog cat bird"来说"dog"就是一个词/词项,而"dog cat"就是一个短语,因此作用范围不一样

2.fuzzy是基于莱文斯坦距离的,所以fuzzy是可以容错的例如你输入"dcg" 你也可以匹配到"dog cat bird",但是这里注意的是你的查询只能是单词条的查询,不能"dcg cat",如果你需要查询短语里面的拼写错误,可以使用match的fuzziness参数,match_phrase是不允许出现不存在的词条的。

下面是对于fuzzy和match_phrase和match 添加fuzziness参数进行对比

文档内容是{"name":"dog cat bird"} 分析器是standard

--------------------------------------------------------------------------------------------------

1.使用拼写错误的"cot"可以使用fuzzy匹配但是,如果是下面这种,短语是不可以的,输入应当是词条,而不是短语

GET test_save/_search

{"query": {"fuzzy": {"name":{"value": "bird cot","fuzziness": 1}

}

}

}

--------------------------------------------------------------------------------------------------

2.这里可以匹配到因为match先分解成bird 和 cot 其中bird可以匹配到,同时cot也是可以匹配到,只不过分数要比输入"bird cat"要低

GET test_save/_search

{"query": {"match": {"name":{"query": "bird cot","fuzziness":1}

}

}

}

-----------------------------------------------------------------------------------------------

3.这里由于cot和文本中的cat不是同一个词,所以是无法匹配到的

GET test_save/_search

{"query": {"match_phrase": {"name": {"query": "bird cot","slop": 1}

}

}

}

以上是对于英文的单词的解析,对于中文其实也是一样,只是由于中文如果使用standard一个词项就是一个字,因此使用因此分词后的数据对于fuzzy模糊匹配来说意义不大,但是可以使用keyword进行

GET test_save/_search

{"query": {"fuzzy": {"name.keyword":{"value": "东日宾馆","fuzziness": 1}

}

}

}

这样是可以匹配到"东方宾馆"的数据的,但是无法匹配"广州东方宾馆"因为莱文斯坦距离已经不止1了

其实短语匹配应该叫临近查询更适合些

以上就是对模糊查询和短语匹配的解析和补充~

[说明]:elasticsearch版本5.6.4

es like模糊匹配_es 基于match_phrase/fuzzy的模糊匹配原理及使用相关推荐

  1. t-s模糊神经网络matlab,基于T-S模型的模糊神经网络,Fuzzy Neural Network based on T-S mode,音标,读音,翻译,英文例句,英语词典...

    补充资料:基于模糊神经网络的模具产品报价系统 一. 报价系统概论 产品报价是指被讯价方根据自身所处市场环境.生产.经营.管理现状等因素而针对讯价方所指定的产品及其特殊的功能需求所报出的价格.产品报价是 ...

  2. 计算机视觉与深度学习 | ORB特征匹配:基于OpenCV+Python(暴力匹配、FLANN)

    ===================================================== github:https://github.com/MichaelBeechan CSDN: ...

  3. 人岗智能匹配,基于记忆的深度文本匹配技术

    向AI转型的程序员都关注了这个号

  4. 最好用的地图匹配框架——基于HMM的Valhalla

    最好用的地图匹配框架--基于HMM的Valhalla 地图匹配 就是将点映射到路段上的技术啦,懂得都懂哈~ 因为本人是做城市计算移动轨迹方面的研究,所以经常要对一些车辆轨迹进行地图匹配,但是由于懒得自 ...

  5. es 模糊查询_ES系列11:Term-level queries 之 3种模糊查询和terms_set query

    [系统学es系列]请移步公众号! 带着问题学习才高效 1.wildcard query.prefix query.fuzzy query这3种模糊查询的异同点是什么? 2.如何使用 terms_set ...

  6. 模糊C均值聚类(Fuzzy C-means)算法(FCM)

    一.FCM算法简介 1.模糊集理论 L.A.Zadeh在1965年最早提出模糊集理论,在该理论中,针对传统的硬聚类算法其隶属度值非0即1的严格隶属关系,使用模糊集合理论,将原隶属度扩展为 0 到 1 ...

  7. 【指纹识别】基于模板匹配算法指纹识别匹配门禁系统matlab源码

    一.简介 1 指纹识别的引入和原理 1.1 指纹的基本知识 指纹,由于其具有终身不变性.唯一性和方便性,已几乎成为生物特征识别的代名词.指纹是指人的手指末端正面皮肤上凸凹不平产生的纹线.纹线有规律的排 ...

  8. 基于SIMULINK的燃烧过程模糊PID控制系统仿真

    基于SIMULINK的燃烧过程模糊PID控制系统仿真 1 燃烧过程控制系统 在许多的工业生产过程中,燃烧都是必需的一环.燃烧过程有燃油.燃煤.燃气等区别.虽然燃烧应用场合和燃料各异,但是燃烧过程的控制 ...

  9. 基于模糊控制(fuzzy control)的PWM直流电机闭环调速系统

    文章目录 摘要 1. 引言 2. 系统总体框图 3. 模糊(Fuzzy)控制算法 4. 软件设计及Proteus仿真 摘要 本文介绍直流电机PWM恒转速闭环调节系统的一种设计方案.系统以单片机AT89 ...

最新文章

  1. R语言实战学习笔记-高级数据管理
  2. ASP.NET Core Web API + Ng6 实战视频 Day 2
  3. 解读:云原生下的可观察性发展方向
  4. MongoDB 学习-MongoDB 的基本操作(二)
  5. 女人在聊天中说给你一个拥抱_不要提高技能; 拥抱一个机器人
  6. ValueError: output parameter for reduction operation logical_and has too many dimensions ?
  7. 百度将于今年下半年推出“哼唱搜索”
  8. 堪萨斯州立大学 计算机科学,美国堪萨斯州立大学排名怎么样?热门专业有哪些...
  9. matlab 取虚数单位,四元数解算姿态Matlab程序代码
  10. mysql 用户、数据库、表的基本操作
  11. java面试死神之蛇形遍历
  12. node.js -- 手把手教你搭建 电商平台
  13. oracle dul误删数据,案例:Oracle dul数据挖掘 没有数据库备份非常规恢复truncate删除的数据表...
  14. SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单
  15. python程序的控制结构思维导图_python学习之路2(程序的控制结构)
  16. Arduino提高篇24—摇杆调节时钟时间
  17. 【Leetcode 3】无重复字符的最长子串
  18. html文件损坏怎么恢复,如何修复损坏Word文档恢复受损文档中的文字
  19. 应急管理指挥中心大数据信息化管控平台建设方案
  20. MATLAB中用imfilter()对图像进行相关或卷积运算前一定要用tofloat()或im2double()将数据类型转换为浮点型

热门文章

  1. Python有哪些好用的语言翻译方法
  2. java 动态创建实例_java – 有没有办法动态创建类(而不是实例)?
  3. androidsdktools安装_如何命令行安装Android SDK Build Tools(构建工具)?
  4. spring拦截器覆盖_Spring中使用Interceptor拦截器
  5. C语言atoi()函数(字符串转整数int类型)(atol()转换为long)
  6. ubuntu 更换系统软件源 和 pip源
  7. SpringMVC(SSM)框架搭建JavaWeb项目时,前端页面文件上传,后台Java下载功能实现及相关问题记录说明
  8. Linux环境下安装OpenOffice 4.1.8
  9. java实验33 类的继承2_java实验2 类的继承性
  10. linux查看硬盘smart_SMART Utility for mac (硬盘检测)