elasticsearch5.1+IK分词器+Java实现近义词功能

说明

  • es版本:5.1.1
  • ik版本:5.1.2
  • 开发:Java,TransportClient

http://blog.csdn.net/tianzhaixing2013/article/details/51506496
上面这个链接的这篇文章是es2.x版本+IK的近义词配置教程,es5.1的话一些地方还不一样。我从这篇文章中学到了不少,在此谢谢作者。
然后自己在此基础上改了改试了试,终于实现了近义词的功能。看网上关于es5.x配置近义词的资料很少,于是用Java api实现了之后,把过程记录下来供新学的小伙伴参考。
(文末也给出了rest接口方式实现的相关说明)

一. 建立Java工程

(略)

二. 新建近义词词库

首先在elasticsearch-5.1.1/config路径下新建近义词词库文件synonyms.txt。编码格式utf-8。
然后写入近义词内容,如下:

儿童, 婴儿, 幼儿, 婴幼儿, 初生儿
文胸 => 文胸, 内衣

这里注意逗号一定要是英文的,我最开始写成了中文的逗号,结果完成之后不起作用也不报错,让我还在怀疑这样的做法有问题。
另外解释下近义词的两种写法:

  • 逗号隔开,如’儿童, 婴儿’。
    可以配置多个词语,只要用逗号隔开就行。
    这种格式代表所有词语之前都是互等的,当你索引内容中有’儿童’时,会将’儿童’分词为’儿童’和’婴儿’,并分别建立一个索引。
  • 箭头隔开,如’文胸 => 文胸, 内衣’。
    箭头左右都可以配置多个词语,也是用逗号隔开。但是这里逗号隔开的词语与上一种格式中’逗号隔开’所代表的意思无关。
    这种格式代表箭头前面的词语可以分词为箭头后面的词语,但是箭头后面的词语不会分词为前面的词语。当你索引内容中有’文胸’时,会分词为’文胸’和’内衣’,并分别建立索引,但是当索引内容为’内衣’时,只会分词为’内衣’。

所以逗号隔开时,会对全部词语都建立索引;箭头隔开时,会对箭头右方的每个词语建立索引。

三. 定义自己的解释器

elasticsearch有一个synonym 的同义词filter,所以为了结合IK,我们需要借助IK定义自己的分词器。
在工程的resource文件夹下新建setting.json。内容如下:

{
    "index": {
        "analysis": {
            "analyzer": {
                "by_smart": {
                    "type": "custom",
                    "tokenizer": "ik_smart",
                    "filter": ["by_tfr", "by_sfr"],
                    "char_filter": ["by_cfr"] },
                "by_max_word": {
                    "type": "custom",
                    "tokenizer": "ik_max_word",
                    "filter": ["by_tfr", "by_sfr"],
                    "char_filter": ["by_cfr"] }
            },
            "filter": {
                "by_tfr": {
                    "type": "stop",
                    "stopwords": [" "] },
                "by_sfr": {
                    "type": "synonym",
                    "synonyms_path": "synonyms.txt" }
            },
            "char_filter": {
                "by_cfr": {
                    "type": "mapping",
                    "mappings": ["| => |"] }
            }
        }
    }
}

这里by_smart和by_max_word就是自定义的分词器,分别使用ik_smart和ik_max_word做tokenizer,配合synonym类型的filter,完成近义词的功能。
char_filter里的by_cfr的作用就是可以把一个字符转换为另一个字符,如’& => and‘。了解更多见官方文档https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-mapping-charfilter.html

四. 定义索引中type的mapping

同样,在工程的resource文件夹下建立mapping.json。内容如下:

{
    "properties": {
        "title": {
            "type": "text",
            "index": "analyzed",
            "analyzer": "by_max_word",
            "search_analyzer": "by_smart"
        }
    }
}

在这里面title字段的分词器就指定成我们之前定义的分词器。

五. 调用api设置解释器和建立索引

......
String mapping = 读取setting.json的字符串;
String settings = 读取mapping.json的字符串;
CreateIndexResponse createIndexResponse = client.admin().indices().prepareCreate("indexname")
                .setSettings(settings)
                .addMapping("typename", mapping)
                .get();
......

六. 测试

分词测试:

curl -XGET 'http://localhost:9200/indexname/_analyze?pretty&analyzer=by_smart' -d '{"text":"儿童"}'

返回结果:

{
  "tokens" : [
    {
      "token" : "儿童",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "婴儿",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "SYNONYM",
      "position" : 0
    },
    {
      "token" : "幼儿",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "SYNONYM",
      "position" : 0
    },
    {
      "token" : "婴幼儿",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "SYNONYM",
      "position" : 0
    },
    {
      "token" : "初生儿",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "SYNONYM",
      "position" : 0
    }
  ]
}

七. REST接口方式(对应三、四、五步)

  1. 设置解释器
curl -XPUT 'http://localhost:9200/indexname' -d' 
{
  "index": {
    "analysis": {
      "analyzer": {
        "by_smart": {
          "type": "custom",
          "tokenizer": "ik_smart",
          "filter": [
            "by_tfr",
            "by_sfr"
          ],
          "char_filter": [
            "by_cfr"
          ]
        },
        "by_max_word": {
          "type": "custom",
          "tokenizer": "ik_max_word",
          "filter": [
            "by_tfr",
            "by_sfr"
          ],
          "char_filter": [
            "by_cfr"
          ]
        }
      },
      "filter": {
        "by_tfr": {
          "type": "stop",
          "stopwords": [
            " "
          ]
        },
        "by_sfr": {
          "type": "synonym",
          "synonyms_path": "synonyms.txt"
        }
      },
      "char_filter": {
        "by_cfr": {
          "type": "mapping",
          "mappings": [
            "| => |"
          ]
        }
      }
    }
  }
}'
  1. 设置type的mapping
curl -XPUT 'http://localhost:9200/indexname/_mapping/typename' -d'
{
  "properties": {
    "title": {
      "type": "text",
      "index": "analyzed",
      "analyzer": "by_max_word",
      "search_analyzer": "by_smart"
    }
  }
}'

至此就是此篇文章的所有内容。有写得不对的地方,欢迎指正。有疑惑的地方,共同交流。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值