分词顾名思义,就是把一句话分红一个一个的词。这个概念在搜索中很重要,好比 This is a banana.
若是按照普通的空格来分词,分红this
,is
,a
,banana
,的出来的a
其实对咱们并无什么用处。所以须要注意下面的问题:java
a
,or
,and
这种都属于停顿词)Banana
与banana
)具体的算法能够参考http://tartarus.org/~martin/PorterStemmer/,对照的词语能够参考这里http://snowball.tartarus.org/algorithms/porter/diffs.txtnginx
相比中文,就复杂的度了。由于中文不能单纯的依靠空格,标点这种进行分词。就好比中华人民共和国国民
,不能简单的分红一个词,也不能粗暴的分红中华人民共和国
和国民
,人民
、中华
这些也都算一个词!git
所以常见的分词算法就是拿一个标准的词典,关键词都在这个词典里面。而后按照几种规则去查找有没有关键词,好比:github
IK,elasticsearch-analysis-ik提供了两种方式,ik_smart
就是最少切分,ik_max_word
则为细粒度的切分(多是双向,没看过源码)算法
了解了分词器的背景后,就能够看一下如何在Elasticsearch重安装分词器了。app
ik GitHub地址:https://github.com/medcl/elasticsearch-analysis-ikcurl
插件包地址:https://github.com/medcl/elasticsearch-analysis-ik/releaseselasticsearch
安装方式:maven
1.解压对应版本的插件包到 your-es-directory/plugins/ik,重启es就ok;ide
2.下载源码,将编译好的jar包导入到 your-es-directory/plugins/ik,重启es就ok;
注意:es 与 ik版本必定要对应。
curl -XPUT http://localhost:9200/ik_index
curl -XPOST http://localhost:9200/ik_index/fulltext/_mapping { "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word" } } }
curl -XPOST http://localhost:9200/index/fulltext/1 -d' {"content":"美国留给伊拉克的是个烂摊子吗"} '
curl -XPOST http://localhost:9200/index/fulltext/2 -d' {"content":"公安部:各地校车将享最高路权"} '
curl -XPOST http://localhost:9200/index/fulltext/3 -d' {"content":"中韩渔警冲突调查:韩警平均天天扣1艘中国渔船"} '
curl -XPOST http://localhost:9200/index/fulltext/4 -d' {"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"} '
curl -XPOST http://localhost:9200/index/fulltext/_search -d' { "query" : { "match" : { "content" : "中国" }}, "highlight" : { "pre_tags" : ["<tag1>", "<tag2>"], "post_tags" : ["</tag1>", "</tag2>"], "fields" : { "content" : {} } } } '
IKAnalyzer.cfg.xml can be located at plugins/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>
目前该插件支持热更新 IK 分词,经过上文在 IK 配置文件中提到的以下配置
<!--用户能够在这里配置远程扩展字典 --> <entry key="remote_ext_dict">location</entry> <!--用户能够在这里配置远程扩展中止词字典--> <entry key="remote_ext_stopwords">location</entry>
其中 location
是指一个 url,好比 http://yoursite.com/getCustomDict
,该请求只需知足如下两点便可完成分词热更新。
该 http 请求须要返回两个头部(header),一个是 Last-Modified
,一个是 ETag
,这二者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
该 http 请求返回的内容格式是一行一个分词,换行符用 \n
便可。
知足上面两点要求就能够实现热更新分词了,不须要重启 ES 实例。
能够将需自动更新的热词放在一个 UTF-8 编码的 .txt 文件里,放在 nginx 或其余简易 http server 下,当 .txt 文件修改时,http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。能够另外作一个工具来从业务系统提取相关词汇,并更新这个 .txt 文件。
pinyin分词器可让用户输入拼音,就能查找到相关的关键词。好比在某个商城搜索中,输入shuihu
,就能匹配到水壶
。这样的体验仍是很是好的。
pinyin分词器的安装与IK是同样的,这里就省略掉了。
这个分词器在1.8版本中,提供了两种分词规则:
pinyin
,就是普通的把汉字转换成拼音;pinyin_first_letter
,提取汉字的拼音首字母github: https://github.com/medcl/elasticsearch-analysis-pinyin
安装: 在github下载源码,idea import 源码,修改pom.xml文件中es版本号,执行maven的package命令,在target目录下的*.zip文件即是pinyin分词器的插件包。安装方式同上IK分词器。
插件介绍:
该插件包括分析器:pinyin,标记器:pinyin和令牌过滤器: pinyin。
**可选参数**
keep_first_letter : 启用此选项时,例如:刘德华> ldh,默认值:true
keep_separate_first_letter : 启用该选项时,将保留第一个字母分开,例如:刘德华> l,d,h,默认:假的,注意:查询结果也许是太模糊,因为长期过频
limit_first_letter_length : 设置first_letter结果的最大长度,默认值:16
keep_full_pinyin : 当启用该选项,例如:刘德华> [ liu,de,hua],默认值:true
keep_joined_full_pinyin : 启用此选项时,例如:刘德华> [ liudehua],默认值:false
keep_none_chinese : 在结果中保留非中文字母或数字,默认值:true
keep_none_chinese_together : 保持非中国信一块儿,默认值:true,如:DJ音乐家- > DJ,yin,yue,jia,当设置为false,例如:DJ音乐家- > D,J,yin,yue,jia,注意:keep_none_chinese必须先启动
keep_none_chinese_in_first_letter : 第一个字母不能是中文,例如:刘德华AT2016- > ldhat2016,default:true
keep_none_chinese_in_joined_full_pinyin : 保持非中文字母加入完整拼音,例如:刘德华2016- > liudehua2016,默认:false
none_chinese_pinyin_tokenize : 打破非中国信成单独的拼音项,若是他们拼音,默认值:true,如:liudehuaalibaba13zhuanghan- > liu,de,hua,a,li,ba,ba,13,zhuang,han,注意: keep_none_chinese和keep_none_chinese_together应首先启用
keep_original : 当启用此选项时,也将保留原始输入,默认值:false
lowercase : 小写非中文字母,默认值:true
trim_whitespace : 默认值:true
remove_duplicated_term : 当启用此选项时,将删除重复项以保存索引,例如:de的> de,默认值:false注意:位置相关查询可能受影响
curl -XPUT http://localhost:9200/medcl { "index" : { "analysis" : { "analyzer" : { "pinyin_analyzer" : { "tokenizer" : "my_pinyin" } }, "tokenizer" : { "my_pinyin" : { "type" : "pinyin", "keep_separate_first_letter" : false, "keep_full_pinyin" : true, "keep_original" : true, "limit_first_letter_length" : 16, "lowercase" : true, "remove_duplicated_term" : true } } } } }
http://localhost:9200/medcl/_analyze?text=%e5%88%98%e5%be%b7%e5%8d%8e&analyzer=pinyin_analyzer
properties 中定义了特定字段的分析方式。在上面的例子中,仅仅设置了content的分析方法。
curl -XPOST http://localhost:9200/medcl/folks/_mapping { "folks": { "properties": { "name": { "type": "keyword", "fields": { "pinyin": { "type": "text", "store": "no", "term_vector": "with_offsets", "analyzer": "pinyin_analyzer", "boost": 10 } } } } } }
http://localhost:9200/medcl/folks/_search?q=name:刘德华 http://localhost:9200/medcl/folks/_search?q=name.pinyin:刘 http://localhost:9200/medcl/folks/_search?q=name.pinyin:liu http://localhost:9200/medcl/folks/_search?q=name.pinyin:ldh http://localhost:9200/medcl/folks/_search?q=name.pinyin:de+hua
curl -XPUT http://localhost:9200/medcl1 { "index" : { "analysis" : { "analyzer" : { "user_name_analyzer" : { "tokenizer" : "whitespace", "filter" : "pinyin_first_letter_and_full_pinyin_filter" } }, "filter" : { "pinyin_first_letter_and_full_pinyin_filter" : { "type" : "pinyin", "keep_first_letter" : true, "keep_full_pinyin" : false, "keep_none_chinese" : true, "keep_original" : false, "limit_first_letter_length" : 16, "lowercase" : true, "trim_whitespace" : true, "keep_none_chinese_in_first_letter" : true } } } } }
Token Test:刘德华 张学友 郭富城 黎明 四大天王
curl -XGET http://localhost:9200/medcl1/_analyze?text=刘德华+张学友+郭富城+黎明+四大天王&analyzer=user_name_analyzer
{ "tokens" : [ { "token" : "ldh", "start_offset" : 0, "end_offset" : 3, "type" : "word", "position" : 0 }, { "token" : "zxy", "start_offset" : 4, "end_offset" : 7, "type" : "word", "position" : 1 }, { "token" : "gfc", "start_offset" : 8, "end_offset" : 11, "type" : "word", "position" : 2 }, { "token" : "lm", "start_offset" : 12, "end_offset" : 14, "type" : "word", "position" : 3 }, { "token" : "sdtw", "start_offset" : 15, "end_offset" : 19, "type" : "word", "position" : 4 } ] }
option 1
PUT /medcl/ { "index" : { "analysis" : { "analyzer" : { "pinyin_analyzer" : { "tokenizer" : "my_pinyin" } }, "tokenizer" : { "my_pinyin" : { "type" : "pinyin", "keep_first_letter":false, "keep_separate_first_letter" : false, "keep_full_pinyin" : true, "keep_original" : false, "limit_first_letter_length" : 16, "lowercase" : true } } } } } GET /medcl/folks/_search { "query": {"match_phrase": { "name.pinyin": "刘德华" }} }
option 2
PUT /medcl/ { "index" : { "analysis" : { "analyzer" : { "pinyin_analyzer" : { "tokenizer" : "my_pinyin" } }, "tokenizer" : { "my_pinyin" : { "type" : "pinyin", "keep_first_letter":false, "keep_separate_first_letter" : true, "keep_full_pinyin" : false, "keep_original" : false, "limit_first_letter_length" : 16, "lowercase" : true } } } } } POST /medcl/folks/andy {"name":"刘德华"} GET /medcl/folks/_search { "query": {"match_phrase": { "name.pinyin": "刘德h" }} } GET /medcl/folks/_search { "query": {"match_phrase": { "name.pinyin": "刘dh" }} } GET /medcl/folks/_search { "query": {"match_phrase": { "name.pinyin": "dh" }} }
整个流程大概是:单词 ====》Character Filter 预处理 =====》tokenizer分词 ====》 token filter对分词进行再处理。
分词配置详解: http://blog.csdn.net/napoay/article/details/53907921
分词过程: http://blog.csdn.net/hu948162999/article/details/68922035
分词原理: http://blog.csdn.net/i6448038/article/details/51509439(推荐)