ES中文分词器之精确短语匹配(解决了match_phrase匹配不全的问题)
分词器选择
调研了几种分词器,例如IK分词器,ansj分词器,mmseg分词器,发现IK的分词效果最好。举个例子:
词:<<是的>><span>哈<\span>撒多撒ئۇيغۇر تىلى王者荣耀sdsd@4342啊啊啊
Standard: 是,的,span,哈,span,撒,多,撒,ئۇيغۇر,تىلى,王,者,荣,耀,sdsd,4342,啊,啊,啊,啊
mmseg_maxword:是,的,span,哈,span,撒,多,撒,ئ,ۇ,ي,غ,ۇ,ر,ت,ى,ل,ى,王者,荣耀,sdsd,4342,啊,啊,啊,啊
IK_max_word:是的,span,哈,span,撒,多,撒,王者,王,者,荣耀,荣,耀,sdsd,4342,sdsd@4342,啊啊啊,啊啊,啊,啊啊,啊
Ansj: <,<,是,的,>,>,<,span,>,哈,<,\,span,>,撒,多,撒,ئ,ۇ,ي,غ,ۇ,ر,ت,ى,ل,ى,王者,荣耀,sdsd,@,4342,啊,啊,啊,啊
在上述例子中,IK和Mmsg 用的同一套词典。Ansj和IK,Mmsg使用的不是一套词典,也没有配置停词。
本文讲的中文分词器就是IK分词器。
分词器需要达到的效果
1)短语可以精确匹配
2)查找时间要比standard少
3)如果查找的词语不在词典中,也必须要查到
4)如果数据在原文中出现,就一定要查全
IK分词器短语精确匹配的问题
楼主意淫着将所有的单字放入词典中,这样用ik_max_word 对数据建索引时既可以把词分出来建索引,又可以把字分出来建索引。然后用 ik_smart 将查找短语,因为ik_smart分出的数据是 ik_max_word 的一个子集,如果要查找的短语在原文中有出现,那么一定可以查到。后来发现用ik_smart分词器查找句子(match_phrase)时一个都没有查到,exo???为什么会查不到呢?明明是一个子集。对此官方网站对match_phrase的解释如下:
Like the match query, the match_phrase query first analyzes the query string to produce a list of terms. It then searches for all the terms, but keeps only documents that contain all of the search terms, in the same positions relative to each other.
意思就是说用match_phrase查找时,查找分词器分出的词的位置和要建索引时分出的词的位置一样。举个例子:
原文:快乐感恩
ik_max_word:快乐 1 快 2 乐感 3 乐 4 感恩 5 感 6 恩 7
ik_smart:快乐 1 感恩 2
从上面可以看出,查找时ik_smart将语句分为了快乐和感恩两个词,位置分别为1和2,而ik_max_word建索引时,快乐和感恩的位置分别是1和4,在match_phrase看来,这种是不匹配的,所以用ik_smart分词短语时无法查到或者查全数据。
好吧,既然ik_smart无法查到,我用ik_max_word查找总行了吧。用上述的例子,查找”快乐“时,你会发现你用ik_max_word查找到的结果没有standard分词器建索引查找获取到的结果多。原因和上述讲的一样:
查找词语:快乐
ik_max_word:快乐 1 快 2 乐 3
在构建索引的时候,快乐,快和乐的位置分别是1,2,4,而查找时分词的顺序是1,2,3,然后match_phrase认为其不匹配,因此查询不到这种结果。
网上答案
遇到问题了,在网上寻求解决方案。看了几篇博客,都指出了match_phrase的这个匹配问题,解决方案有以下两种:
1) standard分词器
2) NGram分词器
standard分词器大家都比较熟,针对于汉字就是一个一个分,这种肯定是可以查全的。但一个一个字分的话,每个字对应的文档集合非常多,如果数据量达到了百亿,在求交集,计算距离时,效果非常差。
Ngram分词器类似于standard分词器,他可以指定分词的长度,然后用standard的方法切割。比如说“节日快乐”,我们指定切割的长度为2,NGram会切成“节日”,“日快”,“快乐”。虽然查找时可以减少每个token对应的文档数,但是存储量会增大很多,而且不在支持模糊的match匹配。很土。
求解过程
ik_max_word构建索引,ik_smart无法查找,原因是ik_max_word分出了所有的词,ik_smart只分出了一种词,由于match_phrase本身的限制导致ik_smart查找不到。那我构建的时候采用ik_smart,查找的时候也用ik_smart,这样只要原文中有数据,构建和查找用同一种分词方法,就应该可以查找得到。测试后发现,这种也有很大的问题,即像“潜行者”这样的词,只分为了“潜行”和“者”两个token,但是“行者”也是一个词,在查找“行者”时无法查全数据。
ik_smart无法查全的原因是只分出了一种词的可能性,导致有些词查询不全。ik_max_word能解决这个问题。。但是ik_max_word的问题是如果查找的最后一个字能和原文中这个字的下一个字组成词语,那么就会出现无法查全的问题。我们能不能让ik_max_word将词和字分开?
当然可以,对一个属性指定两种分词方法:
curl -XPUT 'xxx/my_test_both?pretty' -H 'Content-Type: application/json' -d'
{"mappings": {
"my_type": {
"properties": {
"ulluin": {
"type": "text",
"fields": {
"ik":{"type":"text","analyzer": "ik_max_word"}
}
}
}
}
}
}'
这样ulluin属性采用standard分词,即单字分词,ulluin.ik采用ik_max_word即按词分词,ik_max_word的词典中去除所有的单字。
查询时先将查询短语分词,如果第一个token和最后一个token中存在一个字,那么这个字可能与原文中的下一个字或者上一个字组成词,导致ik_max_word无法查到,这时我们用standard分词器在ulluin中查询,如果第一个token和最后一个token都是词,那么说明可以在ik_max_word中查询。来吧,测试一下:
原文:节日快乐龙哥
ik_max_word:节日 1 快乐龙 2 快乐 3 龙哥 4
查询短语:节日快乐
ik_max_word:节日 1 快乐 2
为什么还是有问题?????ik_max_word查出的数据量比standard的少???还是因为match_phrase的限制,索引中“节日”和“快乐”的位置是1和3,而查找时“节日”和“快乐”的位置是1和2。这个问题很好解决,用match_phrase_prefix查询即可,即:
curl -XGET 'xxx/my_test_both/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"match_phrase_prefix" : {
"ulluin" : {
"query" : "节日快乐"
}
}
},
"size":1
}'
上面还提到ik_max_word有一个问题是分出的词语比standard的多,我们过滤了单字分词后,这个效果就会有很大的提升。假设我们的词典没有四字分词,只有二三字。比如说
原词:中华人民共和国
修改前:中华,中,华人,华,人民,人,民,共和国,共和,和,国
修改后:中华,华人,人民,共和国,共和
可以看出,修改后的效果要比standard的效果好的多,不但token数变少了,而且每个token对应的文档数也大大的降低,减少了求交集的数据量和计算距离的数据量。
至此总算解决了ES中文分词切精确匹配的问题。
作者:YG_9013
链接:https://www.jianshu.com/p/51a756e85eb6
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
ES中文分词器之精确短语匹配(解决了match_phrase匹配不全的问题)的更多相关文章
- ES 中文分词
一.大名鼎鼎的中文插件IK的安装配置 1. 在插件目录中建立IK的目录 mkdir $ES_HOME/plugins/analysis-ik 2. 下载IK 的类库jar 文件到IK目录 cd $ES ...
- ES中文分词器安装以及自定义配置
之前我们创建索引,查询数据,都是使用的默认的分词器,分词效果不太理想,会把text的字段分成一个一个汉字,然后搜索的时候也会把搜索的句子进行分词,所以这里就需要更加智能的分词器IK分词器了. ik分词 ...
- Es学习第五课, 分词器介绍和中文分词器配置
上课我们介绍了倒排索引,在里面提到了分词的概念,分词器就是用来分词的. 分词器是ES中专门处理分词的组件,英文为Analyzer,定义为:从一串文本中切分出一个一个的词条,并对每个词条进行标准化.它由 ...
- [ES]elasticsearch章5 ES的分词(二)
Elasticsearch 中文搜索时遇到几个问题: 当搜索关键词如:“人民币”时,如果分词将“人民币”分成“人”,“民”,“币”三个单字,那么搜索该关键词会匹配到很多包含该单字的无关内容,但是如果将 ...
- 转:从头开始编写基于隐含马尔可夫模型HMM的中文分词器
http://blog.csdn.net/guixunlong/article/details/8925990 从头开始编写基于隐含马尔可夫模型HMM的中文分词器之一 - 资源篇 首先感谢52nlp的 ...
- Elasticsearch之中文分词器插件es-ik(博主推荐)
前提 什么是倒排索引? Elasticsearch之分词器的作用 Elasticsearch之分词器的工作流程 Elasticsearch之停用词 Elasticsearch之中文分词器 Elasti ...
- ElasticSearch搜索引擎安装配置中文分词器IK插件
近几篇ElasticSearch系列: 1.阿里云服务器Linux系统安装配置ElasticSearch搜索引擎 2.Linux系统中ElasticSearch搜索引擎安装配置Head插件 3.Ela ...
- Elasticsearch(10) --- 内置分词器、中文分词器
Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...
- ElasticSearch 中文分词搜索环境搭建
ElasticSearch 是强大的搜索工具,并且是ELK套件的重要组成部分 好记性不如乱笔头,这次是在windows环境下搭建es中文分词搜索测试环境,步骤如下 1.安装jdk1.8,配置好环境变量 ...
随机推荐
- 《vim实用技巧》读书笔记
1. . 命令 2. * 命令 3. cw 命令: (c:修改)会删除从光标位置到单词结尾间的字符,并进入插入模式. eg: cw.copy1 即: 删除从光标位置到单词结尾间的字符,并插入 ...
- Spring NoSQL
把数据收集到一个非规范化的结构中,按照这种方式优化处理文档的数据库称之为文档数据库.文档数据库不适用于数据具有明显关联关系,因为文档数据库并没有针对存储这样的数据进行优化. Spring Data M ...
- CNN 参数计算
CNN 时间计算复杂度与空间复杂度 即,连续个数与参数个数, 每一个连接都意味着一个计算, 每一个参数都意味一个存储单元. 只计算主要部分. CNN局部连接与权值共享 如图所示: 全连接:如左图所示, ...
- PHP设计模式之工厂模式(转)
概念 工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式. 使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地 ...
- 玩vue+mockjs
玩vue+mockjs vue中用mock制造模拟接口(本文主要解决坑),一定要看完哦 最近新入职一家公司,后端造接口速度很慢,想来想去还是搞一套模拟接口,来满足开发需求,有人会问,我造一个死数据不就 ...
- Java依赖注入方式
pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...
- Blender 画正四面体
正四面体打开“添加网格”菜单(Shift + A),然后选择“锥形”.将“顶点数”设置为3,将“半径1”保留为默认值1.000,将“半径2”设置为0.000.现在,将深度设置为 {根号2,约等于1.4 ...
- js中数组的去重
第一种方式: var ss=['小红','小花','小兰','小花'] var uu=[] for(var i=0;i<ss.length;i++){ if(uu.indexOf(ss[i])= ...
- 初始if..else 条件语句
if..else条件语句 如果我们希望有效的响应用户的输入,代码就需要具有判断能力.能够让程序进行判断的结构成为条件,条件判断语句返回的是布尔值真或假,真就执行一条线路,假就执行另外一条线路 if 条 ...
- 下载B站、秒拍等视频网站视频
需要一个FVD Downloader(插件) 安装过程很简单,会浏览器安装插件的就不多说了!