大数据求索(10): 解决ElasticSearch中文搜索无结果------ik分词器的安装与使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wen_fei/article/details/85211677

大数据求索(10): 解决ElasticSearch中文搜索无结果-----IK中文分词器的安装与使用

问题所在

在中文情况下,ES默认分词器会将汉字切分为一个一个的汉字,所以当搜索词语的时候,会发现无法找到结果。

解决办法

有很多其他的分词器插件可以替代,这里使用最常用的IK分词器。

IK分词器安装

注意:

ik分词器必须和ES版本严格对应,否则可能会产生意料之外的错误。

Github地址:https://github.com/medcl/elasticsearch-analysis-ik

可以直接下载releases下面的源码,使用maven进行编译。

把下载的elasticsearch-analysis-ik.zip解压

进入elasticsearch-analysis-ik-master/ 下,打包。

mvn clean package

打包后的文件在elasticsearch-analysis-ik-master/target/relearses目录下,名称类似如下,是一个zip文件。

elasticsearch-analysis-ik-5.6.2.zip

在/home/hadoop/cluster/elasticsearch/plugins创建ik文件夹,并将打包后的zip文件解压到此文件夹下,此时ik目录下一般有如下几个文件

commons-codec-1.9.jar    config                              httpclient-4.5.2.jar     plugin-descriptor.properties
commons-logging-1.2.jar  elasticsearch-analysis-ik-5.6.2.jar  httpcore-4.4.4.jar

此时,重启ES即可。

IK分词器的使用

使用IK分词器,由于认识较浅,只找到一种方法,就是改变ES中index的mapping。此外,由于mapping一旦创建就无法修改,所以,只能重新创建一个新的index,里面没数据 ,并设置mapping。java代码举例如下:

/**
     * 重新生成mapping,使用ik分词器
     * @throws Exception
     */
    @Test
    public void setMapping() throws Exception {
        TransportClient client = getClient();

        // 设置mapping,使用ik分词器
        // 没有数据之前才能成功,如果已经有mapping,则无法重新创建
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("article")
                .startObject("properties")
                .startObject("title").field("type", "text").field("store", "yes").field("analyzer", "ik_smart").field("search_analyzer","ik_max_word").endObject()
                .endObject()
                .endObject()
                .endObject();
        PutMappingRequest mapping = Requests.putMappingRequest("blog2").type("article").source(builder);
        client.admin().indices().putMapping(mapping).actionGet();
        client.close();
    }

重新生产mapping以后,可以通过head插件查看,发现新的index的mapping如下:

{
"state": "open",
"settings": {
"index": {
"creation_date": "1545450199648",
"number_of_shards": "5",
"number_of_replicas": "1",
"uuid": "1GGDZoVqQV6YsRv0Sbu3gg",
"version": {
"created": "5060299"
},
"provided_name": "blog2"
}
},
"mappings": {
"article": {
"properties": {
"id": {
"type": "text",
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
}
},
"title": {
"search_analyzer": "ik_max_word",
"analyzer": "ik_smart",
"store": true,
"type": "text"
},

注意到title的search_analyzer和analyzer已经修改为ik分词器了,下面进行测试,首先插入两条数据,如下所示

{
"_index": "blog2",
"_type": "article",
"_id": "2",
"_version": 1,
"_score": 1,
"_source": {
"id": "2",
"title": "基于深度学习的搜索",
"content": "test"
},
{
"_index": "blog2",
"_type": "article",
"_id": "1",
"_version": 1,
"_score": 1,
"_source": {
"id": "1",
"title": "基于Lucene的搜索服务器",
"content": "提供分布式全文搜索"
}
}

}

进行模糊查询,代码如下

/**
     * 模糊查询
     */
    @Test
    public void fuzzy() throws Exception {
        TransportClient client = getClient();
        SearchResponse searchResponse = client.prepareSearch("blog2")
                .setTypes("article")
                // 重新构造分词器以后才可以搜索成功,否则默认将汉字切分为单个字,所以无法检索到结果
                .setQuery(QueryBuilders.fuzzyQuery("title", "基于"))
                .get();
        // 获取命中次数,查询结果有多少对
        SearchHits hits = searchResponse.getHits();

        System.out.println("查询结果有:" + hits.getTotalHits() + "条");

        Iterator<SearchHit> iterator = hits.iterator();
        while (iterator.hasNext()) {
            SearchHit searchHit = iterator.next();
            System.out.println(searchHit.getSourceAsString());
        }

        client.close();
    }

此时结果如下

查询结果有:2条
{"id":"2","title":"基于深度学习的搜索","content":"test"}
{"id":"1","title":"基于Lucene的搜索服务器","content":"提供分布式全文搜索"}

可以进行词语级别的查询,IK分词器使用成功。

IK不同版本之间可能有小的差异,具体可以参考官方github配置。

参考

  1. 官方github地址 https://github.com/medcl/elasticsearch-analysis-ik

猜你喜欢

转载自blog.csdn.net/wen_fei/article/details/85211677