分詞顧名思義,就是把一句話分紅一個一個的詞。這個概念在搜索中很重要,好比 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(推薦)