Elasticsearch中文分词

分词器介绍:

在使用 Elasticsearch 搜索中文信息时,Elasticsearch 默认将中文切分为单个汉字,对于常见的人名、地名、机构名等则无法优雅的处理,此时就需要用到一些中文分词器,常见的分词器如下:

- Standard 默认分词器

- IK 中文分词器

- Pinyin 分词器

- Smart Chinese 分词器

- Hanlp 中文分词器

中文分词器比较:

分词器

分词结果

查全率

查准率

查询性能

默认 standard

南/京/市/长/江/大/桥

IK 分词器 ik_max_word

南京市/南京/市长/长江大桥/长江/大桥

IK 分词器 ik_smart

南京市/长江大桥

Smart Chinese 分词器

南京市/长江/大桥

Hanlp 中文分词器

南京市/长江大桥

Pinyin 分词器

南京市长江大桥/njscjdq/nan/jing/shi/chang/jiang/da/qiao

  • Standard 默认分词器,对单个字符进行切分,查全率高,准确度较低
  • IK 分词器 ik_max_word:查全率高,性能也较高,是业务中普遍采用的中文分词器
  • IK 分词器 ik_smart:切分颗粒度较粗,查全率不高,但是查准率、查询性能较高
  • Smart Chinese 分词器:查准率、查询性能较高
  • Hanlp 中文分词器:切分颗粒度较粗,查准率较高
  • Pinyin 分词器:针对汉字拼音进行的分词器,与上面介绍的分词器稍有不同,在用拼音进行查询时查全率准确度较高

下面详细介绍下各种分词器,对同一组汉语进行分词的结果对比,方便大家在实际使用中参考。

Standard 默认分词器

GET _analyze
{
  "text": "南京市长江大桥",
  "tokenizer": "standard"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "南"
    },
    {
      "token" : "京",
    },
    {
      "token" : "市",
    },
    {
      "token" : "长",
    },
    {
      "token" : "江",
    },
    {
      "token" : "大",
    },
    {
      "token" : "桥",
    }
  ]
}

默认分词器处理中文是按照单个汉字进行切割,不能很好的理解中文词语的含义,在实际项目使用中很少会使用默认分词器来处理中文。

IK 中文分词器:

插件下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

(注意必须下载和使用的 Elasticsearch 匹配的版本)

1. 执行插件安装命令:

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.0/elasticsearch-analysis-ik-7.10.0.zip


2. 重启 ES 即生效

IK 分词器包含:ik_smart 以及 ik_max_word 2种分词器,都可以用在 索引和查询阶段。

创建一个索引,里面包含2个字段:

- 字段 max_word_content 使用 ik_max_word 分词器处理;

- 字段 smart_content 采用 ik_smart 分词器处理;

分别对比下执行结果:


#创建索引
PUT /analyze_chinese
{
  "mappings": {
    "properties": {
      "max_word_content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_max_word"
      },
      "smart_content": {
        "type": "text",
        "analyzer": "ik_smart",
        "search_analyzer": "ik_smart"
      }
    }
  }
}
#添加测试数据
POST analyze_chinese/_bulk
{"index":{"_id":1}}
{"max_word_content":"南京市长江大桥","smart_content":"我是南京市民"}

# ik_max_word 查询分析器解析结果
POST _analyze
{
  "text": "南京市长江大桥",
  "analyzer": "ik_max_word"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "南京市",
    },
    {
      "token" : "南京",
    },
    {
      "token" : "市长",
    },
    {
      "token" : "长江大桥",
    },
    {
      "token" : "长江",
    },
    {
      "token" : "大桥",
    }
  ]
}
#ik_smart
POST _analyze
{
  "text": "南京市长江大桥",
  "analyzer": "ik_smart"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "南京市",
    },
    {
      "token" : "长江大桥",
    }
  ]
}

通过以上分析,ik_smart 显然分词的颗粒度较粗,而 ik_max_word 颗粒度较细

通过 DSL 来验证查询

POST analyze_chinese/_search
{
  "query": {
    "match": {
      "smart_content": "南京市"
    }
  }
}
#返回结果
"hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }


未匹配到记录,因为 “我是南京市民” 经过分词处理后并不包含 “南京市” 的 token,那通过 “南京” 搜索呢?

POST analyze_chinese/_search
{
  "query": {
    "match": {
      "smart_content": "南京"
    }
  }
}
#返回结果
"hits" : [
      {
        "_source" : {
          "max_word_content" : "南京市长江大桥",
          "smart_content" : "我是南京市民"
        }
      }
    ]


经过 ik_max_word 分词处理器处理之后的 max_word_content 字段效果呢?

POST analyze_chinese/_search
{
  "query": {
    "match": {
      "max_word_content": "南京"
    }
  }
}
#返回结果
"hits" : [
      {
        "_source" : {
          "max_word_content" : "南京市长江大桥",
          "smart_content" : "我是南京市民"
        }
      }
    ]
#使用 南京市 查询
POST analyze_chinese/_search
{
  "query": {
    "match": {
      "max_word_content": "南京市"
    }
  }
}
#返回结果
"hits" : [
      {
        "_source" : {
          "max_word_content" : "南京市长江大桥",
          "smart_content" : "我是南京市民"
        }
      }
    ]

可以看到,由于 “南京市长江大桥” 经过 ik_max_word 分词器处理后,包含 “南京市” token,所以都可以查询到。

IK 分词器总结:

- ik_max_word 分词颗粒度小,查全率高,满足业务场景更丰富

- ik_smart 分词器颗粒度较粗,满足查准要求高的业务

pinyin 分词器

首先,下载 pinyin 分词器插件:https://github.com/medcl/elasticsearch-analysis-pinyin

本地编译并打包后,上传到 ES 安装目录下的 plugins 下并解压,然后重启 ES,重启后查看是否安装成功:

./bin/elasticsearch-plugin list
ik
pinyin


可以看到 pinyin 插件已经安装成功

PUT /analyze_chinese_pinyin/ 
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "pinyin_analyzer" : {
                    "tokenizer" : "my_pinyin"
                    }
            },
            "tokenizer" : {
                "my_pinyin" : {
                    "type" : "pinyin",
                    "keep_separate_first_letter" : false,
                    "keep_full_pinyin" : true,
                    "keep_original" : true,
                    "limit_first_letter_length" : 16,
                    "lowercase" : true,
                    "remove_duplicated_term" : true
                }
            }
        }
    }
}

GET /analyze_chinese_pinyin/_analyze
{
  "text": ["南京市长江大桥"],
  "analyzer": "pinyin_analyzer"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "nan",
    },
    {
      "token" : "南京市长江大桥",
    },
    {
      "token" : "njscjdq",
    },
    {
      "token" : "jing",
    },
    {
      "token" : "shi",
    },
    {
      "token" : "chang",
    },
    {
      "token" : "jiang",
    },
    {
      "token" : "da",
    },
    {
      "token" : "qiao",
    }
  ]
}
#设置测试数据
POST analyze_chinese_pinyin/_bulk
{"index":{"_id":1}}
{"name":"南京市长江大桥"}

#根据拼音查询 njscjdq
POST analyze_chinese_pinyin/_search
{
  "query": {
    "match": {
      "name.pinyin": "njscjdq"
    }
  }
}
#返回结果
"hits" : [
      {
        "_source" : {
          "name" : "南京市长江大桥"
        }
      }
    ]
#通过 nan 查询
POST analyze_chinese_pinyin/_search
{
  "query": {
    "match": {
      "name.pinyin": "nan"
    }
  }
}
#返回结果
"hits" : [
      {
        "_source" : {
          "name" : "南京市长江大桥"
        }
      }
    ]

因为 南京长江大桥 经过 pinyin_analyzer 分词器分词后,包含 nan 和 njscjdq 所以都能匹配查询到记录

Smart Chinese Analysis

参考:https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html

Smart Chinese Analysis 插件将 Lucene 的智能中文分析模块集成到 Elasticsearch 中,

提供了中文或中英文混合文本的分析器。该分析器使用概率知识来找到简体中文文本的最佳分词。文本首先被分解成句子,然后每个句子被分割成单词。

此插件必须在每个节点上安装且需要重启才生效,此插件提供了 smartcn 分析器、smartcn_tokenizer tokenizer 等。

/bin/elasticsearch-plugin install analysis-smartcn
-> Installing analysis-smartcn
-> Downloading analysis-smartcn from elastic
[=================================================] 100%   
-> Installed analysis-smartcn


同样执行查看已安装插件的列表

./bin/elasticsearch-plugin list
analysis-smartcn
ik
pinyin


安装成功后,需要重启 ES 以便插件生效

POST _analyze
{
  "analyzer": "smartcn",
  "text":"南京市长江大桥"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "南京市",
    },
    {
      "token" : "长江",
    },
    {
      "token" : "大桥",
    }
  ]
}

hanlp 中文分词器

安装插件:

./bin/elasticsearch-plugin install https://github.com/KennFalcon/elasticsearch-analysis-hanlp/releases/download/v7.10.0/elasticsearch-analysis-hanlp-7.10.0.zip


安装后查看插件安装情况,安装成功后也同样需要重启 ES

./bin/elasticsearch-plugin list
analysis-hanlp
analysis-smartcn
ik
pinyin


GET _analyze
{
  "text": "南京市长江大桥",
  "tokenizer": "hanlp"
}
#返回结果
{
  "tokens" : [
    {
      "token" : "南京市",
    },
    {
      "token" : "长江大桥",
    }
  ]
}


小结:

通过以上比较,没有哪一种分词器能处理各种不同的场景需求,在实际业务开发中,要根据不同的业务场景、不同的字段设置不同的分词器,以满足实际业务的需要。


上一篇:CCFadeOut ,CCFadeIn 不能使用的原因


下一篇:【android学习2】:Eclipse中HttpServlet类找不到