ES - 中文分词及高亮搜索

包括内容:

IK分词组件的添加和配置

索引建立及高亮搜索示例

添加自定义分词的测试

版本: 

ES - 2.4.5, IK - 1.10.5 
ps: 5.0的版本, 配置和验证代码都不是太一样, 以下应该只适用于2.x版本

IK Analyzer是一个开源的, 基于java语言开发的轻量级的中文分词工具包, 应该是目前比较公认的适合ES的中文分词方案, 因为它默认实现了针对luence的优化. 下面会先介绍安装配置方法, 再介绍应用. 

Analyzer:ik_smart,ik_max_word, Tokenizer:ik_smart,ik_max_word

这里假设我们已经配置好了ES集群 [这个确实很简单, 因为es的默认配置就已经很好]

推荐使用rpm的安装方式:

一 下载对应的IK版本
https://github.com/medcl/elasticsearch-analysis-ik

二 下载pre-build, 或者自行编译

工程是pom, 需要安装maven,
git clone https://github.com/medcl/elasticsearch-analysis-ik
cd elasticsearch-analysis-ik
git checkout tags/{version}
mvn clean
mvn compile
mvn package

我其实是直接下载的pre-build, elasticsearch-analysis-ik-1.10.5.zip

三 配置

First, 解压elasticsearch-analysis-ik-1.10.5.zip, 拷贝到plugins/analysis-ik下, 如果是rpm安装的, 则对应的目录为/usr/share/elasticsearch/plugins/analysis-ik

Second, 修改elasticsearch的配置文件,指定IK为分词工具。打开/etc/elasticsearch/elasticsearch.yml, 最后添加 [这不应该也不用做, 我有两个节点没做也是没问题的, 所以官方文档是对的]:

    index.analysis.analyzer.default.type: ik

Last, 词典. 看到很多人写的安装引导都提到了将词典拷贝到es的config目录, 亲测这一步是不需要的. 

验证: 最好还是用浏览器直接验证, 命令行的话还需要处理编码问题

(虽然, 官方说明说在某个索引下调用接口测试, 如果是单点测试的话, 其实没什么差异, 但是要是集群的话指定的index决定了在哪个节点执行)

http://localhost:9200/ik_index/_analyze?text=我是中国人&tokenizer=ik&pretty=true
http://localhost:9200/_analyze?analyzer=ik&pretty=true&text=我是中国人

analyzer目前支持两种, ik_max_word和ik_smart, 他们的区别在于分词的粒度

ik_max_word: "我是中国人" --> "我, 中国人, 中国, 国人"

ik_smart: "我是中国人" --> "我, 中国人"

官方文档分词测试验证: 

PS: 个人比较喜欢kopf这个插件, 简洁, 清晰, 

1 创建ik_index

PUT http://localhost:9200/ik_index

2 创建mapping

POST http://localhost:9200/ik_index/fulltext/_mapping -d'
{
"fulltext":
      {"_all": {
         "analyzer": "ik_max_word",
         "search_analyzer": "ik_max_word",
         "term_vector": "no","store": "false"
      },
        "properties": {
               "content": {
                    "type": "string",
                    "store": "no",
                    "term_vector": "with_positions_offsets",
                    "analyzer": "ik_max_word",
                    "search_analyzer": "ik_max_word",
                    "include_in_all": "true",
                    "boost": 8}}
}}'

3 index some docs

curl -XPOST http://localhost:9200/ik_index/fulltext/1 -d'{"content":"美国留给伊拉克的是个烂摊子吗"}'

curl -XPOST http://localhost:9200/ik_index/fulltext/2 -d'{"content":"公安部:各地校车将享最高路权"}'

curl -XPOST http://localhost:9200/ik_index/fulltext/3 -d'{"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"}'

curl -XPOST http://localhost:9200/ik_index/fulltext/4 -d'{"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"}'

4 query with highlighting

curl -XPOST http://localhost:9200/ik_index/fulltext/_search  -d'
{
"query" :{ "term" : { "content" : "中国" }},
"highlight" : {"pre_tags" : ["", ""],
"post_tags" : ["", ""],
"fields" : {"content" : {}}}
}'

result:

Dictionary Configuration:

IKAnalyzer.cfg.xml can be located at{conf}/analysis-ik/config/IKAnalyzer.cfg.xml or {plugins}/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml

热更新 IK 分词使用方法

目前该插件支持热更新 IK 分词,通过上文在 IK 配置文件中提到的如下配置

其中location是指一个 url,比如http://yoursite.com/getCustomDict,该请求只需满足以下两点即可完成分词热更新。

1. 该 http 请求需要返回两个头部(header),一个是Last-Modified,一个是ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。

2. 该 http 请求返回的内容格式是一行一个分词,换行符用\n即可。

满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。

可以将需自动更新的热词放在一个 UTF-8 编码的 .txt 文件里,放在 nginx 或其他简易 http server 下,当 .txt 文件修改时,http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。可以另外做一个工具来从业务系统提取相关词汇,并更新这个 .txt 文件。

添加分词测试:

公司名称叫小鱼易连, 小鱼是可以被识别成一个词的, 但是易连就不认了, 效果如下

localhost:9200/_analyze?analyzer=ik&pretty=true&text=小鱼易连

这可不是我期望的, 用户在搜产品文档的时候输入"易连"找不到结果可不行, 其实很简单, 有两种方法:

一个是根据上面提到的热更新方法, 通过插件自动抓取扩展词典的变化更新词库. 

另外一个, 我们可以快速验证, 通过更改config/custom下的mydict.dic, 在文件结尾添加"易连"即可, 不过需要重启服务加载词库.效果如下:

可以看到, 文档6的得分明显高于文档5, 您可以用5秒钟思考一下为什么.

及时只搜索"易连", 文档6同样相关度更高

答案是, 文档6在索引时, 添加了"小鱼易连"这个分词, 关于这个评分, 因为会做一个站内搜索功能, 以后会单独分享一次, 包括高亮的介绍.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容