概述

  1. 分词有什么作用:默认的分词器会将一句话分成一个个单独的字,适用范围广,但是精准度低(索引中和查询语句中有相同的字就会匹配上),所以在配置mapping的时候给需要搜索的中文字段设置分词器,一般需要搜索的中文字段都需要单独设置分词器
"user": {  "type": "text",  "analyzer": "ik_max_word",  "search_analyzer": "ik_max_word"}


analyzer是字段文本的分词器(建索引时分词),search_analyzer是搜索词的分词器(查询时分词)

目前存在的问题:

  1. 自定义的词在搜索的结果中分数不是最高的

分词器类型:ik

 

分词模式:ik_max_word,ik_smart

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。

分词器安装 :

下载zip包并安装:https://github.com/medcl/elasticsearch-analysis-ik(选择与elasticsearch对应的版本)

按如上步骤或者下载zip包解压到elasticsearch的plugins的ik文件夹下

自定义词典配置:

ik目录下config文件夹IKAnalyzer.cfg.xml文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"><properties>	<comment>IK Analyzer 扩展配置</comment>	<!--用户可以在这里配置自己的扩展字典 -->	<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>	 <!--用户可以在这里配置自己的扩展停止词字典-->	<entry key="ext_stopwords">custom/ext_stopword.dic</entry> 	<!--用户可以在这里配置远程扩展字典 -->	<entry key="remote_ext_dict">location</entry> 	<!--用户可以在这里配置远程扩展停止词字典-->	<entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry></properties>


 注意:

如果自定义词典没生效,请确保你的扩展词典的文本格式为 UTF-8 编码,且每个词占一行,例子里的文件路径为相对路径

测试分词结果:

POST http://localhost:9200/_analyze{    "analyzer":"ik_max_word",    "text":"死亡人数"}


存在的问题:

已解决(可能存在):

1.需要词典热更新

在apache-tomcat-5.5\webapps\ROOT目录下添加词典,词典需为txt格式并且为UTF-8无bom编码,然后在ik配置文件IKAnalyzer.cfg.xml中配置词典的url   http://localhost:端口号/文件名

未解决:

1.设置 "analyzer": "ik_max_word",

  "search_analyzer": "ik_max_word"

在词典配置“死亡人数”后,当索引有“死亡人数”,“死亡”,“人数”这几个词的不同语句时,自定义的词“死亡人数”不一定排在前面

分词器类型:ansj

分词模式:idnex_ansj,query_ansj,dic_ansj

index_ansj 是索引分词,尽可能分词处所有结果,词典的词和单个的字都会被分出来

query_ansj 是搜索分词,是索引分词的子集,保证了准确率

dic_ansj 是用户自定义词典优先策略

注:另外几个是别名

分词器安装 :

下载zip包并安装:https://github.com/NLPchina/elasticsearch-analysis-ansj(选择与elasticsearch对应的版本)

安装方式同ik

自定义词典配置:

如上链接,需注意必须改配置文件,不然词典加载不成功:

#用户自定词典配置  dic: default.dic #也可以写成 file//default.dic , 如果未配置dic,则此词典默认加载  # http方式加载  #dic_d1: http://xxx/xx.dic  # jar中文件加载  #dic_d2: jar://org.ansj.dic.DicReader|/dic2.dic  # 从数据库中加载  #dic_d3: jdbc:mysql://xxxx:3306/ttt?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull|username|password|select name as name,nature,freq from dic where type=1  # 从自定义类中加载,YourClas  extends PathToStream  #dic_d3: class://xxx.xxx.YourClas|ohterparam


dic后的词典文件最好写成file格式的,直接写词典名会包找不到文件的错,自定义词典和默认的词典都写file格式,以.dic结尾,以UTF-8编码

  1. 如果需要配置多个词典,目前我知道两种方式
    第一种是直接在默认词典里面添加自己需要的特殊词,第二种是在elasticsearch/bin下配置ansj_library.properties,文件格式dic=library , library为elasticsearch/bin词典文件夹,将不同的词典文件添加到此目录下,以.dic结尾(已测试过可行)

测试分词结果:

POST http://localhost:9200/_analyze{    "analyzer":"index_ansj",    "text":"死亡人数"}


存在的问题:

还是分词结果优先级没解决

尝试:

方案一:

改mapping配置为:

"analyzer": "index_ansj",
"search_analyzer": "query_ansj"

可以搜到词典中存在的最长的词,但是query_ansj不能分出更细粒度的词,就如“死亡人数”,query_ansj分词结果为“死亡人数”一个词,“死亡”和“人数”不在分词结果中,与预期结果不符合,同理dic_ansj和query_ansj的分词结果相同。

方案二:

改mapping配置为:

"analyzer": "index_ansj",
"search_analyzer": "index_ansj"

index_ansj分出的词是细粒度的,如“死亡人数”的分词结果是“死亡人数”“死亡”“人数”,满足了对不同词有结果的要求,但同时也将“死亡人数”拆分成四个单独的字存在于分词结果中,这样会大大降低结果的准确性

方案三:ik和ansj结合使用

"analyzer": "ik_max_word",
"search_analyzer": "index_ansj"

和上面结果类似。

也就是说通过设置mapping的分词器方式无法解决这个问题