elastic search6.2.4配置同义词典synonys

需求:有一个字段item_name,两条数据

出租车

出租汽车

如果使用ik_smart分词,出租车和出租汽车都不会分词

如果使用ik_max_word分词,出租车分为出租车、出租、租车。出租汽车分为出租汽车、出租、汽车。

搜索端使用的分词是ik_smart,而索引使用的分词是ik_max_word。

那当我搜索“出租车”的时候,是搜索不到出租汽车的

当我搜索“出租汽车”的时候,是搜索不到出租车的。

 

如果我搜索端使用的分词是ik_max_word,那我可能搜索到很多不想搜索到的内容,比如可能会搜索到“房屋出租”

 

扫描二维码关注公众号,回复: 2484395 查看本文章

解决方法:使用近义词组件

近义词组件已经是elasticsearch自带的了,所以不需要额外安装插件。

 

elastic synonym token filter官方参考:

Synonym Token Filter

想要ik analysis中使用synonym token filter,需要配置自己的分析器

 

创建一个test_index

PUT test_index
{
  "settings": {
    "number_of_shards": 1, 
    "analysis": {
      "filter": {
        "my_synonym_filter":{
          "type":"synonym",
          "synonyms_path":"analysis-ik/synonym.txt"
        }
      },
      "analyzer": {
        "ik_syno":{
          "type":"custom",
          "tokenizer":"ik_smart",
          "filter":["my_synonym_filter"]
        },
        "ik_syno_max":{
          "type":"custom",
          "tokenizer":"ik_max_word",
          "filter":["my_synonym_filter"]
        }
      }
    }
  },
  "mappings": {
    "doc":{
      "properties": {
        "item_name":{
          "type": "text",
          "analyzer": "ik_syno_max",
          "search_analyzer": "ik_syno_max"
        }
      }
    }
  }
}

在elasticsearch plugins 下的analysis-ik下新增synonym.txt文件

其中synonym.txt中配置

出租车,出租汽车

 

synonym.txt的配置规则是:

a,b => c

a,b,c

 

第一种在分词的时候,a,b都会解析成为c,然后把c存入索引中

第二种在分词的时候,有a的地方,都会解析成a,b,c,把a,b,c存入索引中

添加两条测试数据

POST test_index/doc
{
  "item_name":"对违反出租车运营规定的处罚"
}

POST test_index/doc
{
  "item_name":"出租汽车经营者不按照规定配置出租汽车相关设备"
}

查询一下

GET test_index/doc/_search
{
  "query": {
    "match": {
      "item_name": "出租汽车"
    }
  }
}

GET test_index/doc/_search
{
  "query": {
    "match": {
      "item_name": "出租车"
    }
  }
}

都是可以搜索到的,实现了我们的需求

参考:安装elasticsearch及中文IK和近义词配置

另外,还有一个热更新的问题

有一个解决方案是修改IK分词器的源码,基于mysql来热更新词库。

 

思路是:

ik-analysis在内存中维护了一个_MainDict。

新建一个线程,这个线程在项目启动的时候启动,之后查询数据库,将数据库中配置的词添加到内存_MainDict中,然后Thread.sleep 1秒。之后继续重复。

这样当进行分词的时候,从内存中取到的_MainDict基本上是最新的。

 

这样有两个好处:

1. 不需要重启es就能生效

2. 由于es是分布式的,可能有数百个节点,这样你就不用每次都一个一个节点上面去修改ik分词的词库了。

 

但这样的热更新也要思考

对于1,如果es不重新创建索引,那么即便es热更新对应这些词语,由于索引中的字段未更新,还是搜索不到的。

所以热更新的应用是有条件的。

比如说你的索引中只有几条与之相关的,那么你数据库中确定好,修改其modify_time,之后让logstash来更新这几条索引。

如果你的索引中很多条与之相关,那么还是要全部更新es相应索引。

 

对于2,这个的的确确是热更新的好处,但就目前我们集群两台机器,不需要这样做,比如添加近义词到synonym.txt中,那就在两台机器中的synonym.txt中都添加就可以了

 

基于以上,目前并没有采用基于mysql的热更新词库的功能

猜你喜欢

转载自blog.csdn.net/u013905744/article/details/81084369
今日推荐