Skip to content

Elasticsearch 使用 IK Analysis 实现中文分词

🏷️ Elasticsearch

IK Analysis for Elasticsearch : medcl / elasticsearch-analysis-ik

Install

  1. 下载预编译包安装

ElasticSearch 根目录的 plugins 文件夹下创建 ik 文件夹。

bash
cd your-es-root/plugins/ && mkdir ik

解压下载的预编译包文件到 your-es-root/plugins/ik

  1. 使用 elasticsearch-plugin 安装
bash
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip

常见问题

  1. 分词测试失败 请在某个索引下调用 analyze 接口测试,而不是直接调用 analyze 接口 如:
bash
curl -XGET "http://localhost:9200/your_index/_analyze" -H 'Content-Type: application/json' -d'
{
   "text":"中华人民共和国 MN","tokenizer": "my_ik"
}'
  1. ik_max_wordik_smart 什么区别?

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

SpringBoot & IK Analysis

实体定义

没有对应的索引时,会自动根据实体定义中的注解生成对应的索引。

注意:仅在应用启动时会根据注解的设置生成索引。如果应用运行的过程中删除了索引,之后再向索引中新增数据时,仅会根据默认设置生成索引。如 String 类型会默认定义为 keyword 类型,也不会使用指定的分词设置。

java
/**
* 名称
*/
@Field(store = true, index = true, type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String title;

上面代码生成的 field 属性如下:

json
{
    "mappings": {
        "elasticentitytype": {
            "properties": {
                "title": {
                    "analyzer": "ik_max_word",
                    "store": true,
                    "type": "text"
                }
            }
        }
    }
}

查询示例

java
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
if (StringUtils.isNotEmpty(parameter.getKey())) {
    queryBuilder.should(QueryBuilders.matchQuery("title", parameter.getKey()));
}

Sort sort = Sort.by("createTime").descending();
Pageable pageable = PageRequest.of(parameter.getIndex() * parameter.getSize(), parameter.getSize(), sort);
Page<Blog> blogs = blogRepository.search(queryBuilder, pageable);

matchPhraseQuerymatchQuery 的区别

matchPhraseQuerymatchQuery 等的区别,在使用 matchQuery 等时,在执行查询时,搜索的词会被分词器分词,而使用 matchPhraseQuery 时,不会被分词器分词,而是直接以一个短语的形式查询,而如果你在创建索引所使用的 fieldvalue 中没有这么一个短语(顺序无差,且连接在一起),那么将查询不出任何结果。