Elasticsearch 分词

所谓分词就是将一段文本按照语义规则切分成多个词语,当有一篇文章标题是 “马云说996是福报”时,我们需要把这段文本切分成多个词语: 996、马云、福报 等。因为用户搜索的时候可能只会输入一个词语。

之所以要这样做是为了提高搜索的准确度,如果用户搜索的时候输入的关键字是 “996”,刚好能匹配到分词短语 996,就能命中该文本。ES 的搜索不象 MySQL 那样使用 like 语句执行模糊搜索。

搜索的质量取决于分词的好坏。例如 996 如果拆分成9和6,用户输入996又匹配不到,输入9或者6 可能又会搜到很多无关紧要的东西。

分析器

分析器的作用对文本进行分词处理。首先将文本拆分,构建倒排索引,然后对分词进行处理提高分词的搜索准确率。分析器包含3个功能

  • 字符过滤器:将文本中的特殊字符过滤,例如html标签,标点符号
  • 分词器:将文本拆分成单个词条
  • Token 过滤器:对词条进一步优化,单词小写话,删除无用词(的、得、地)等操作

将文档加入索引或者用户搜索的时候都会用到分析器。分析器有很多种,下面将对常用的分析器介绍

空格分析器

空格分析器只适用于英文文本,它按照单词的空格进行切分。因为中文句子是连续的,所以空格分析器不使用。

POST _analyze

{
  "analyzer": "whitespace",
  "text":     "The quick brown fox."
}

# 输出
{
    "tokens": [
        {
            "token": "The",
            "start_offset": 0,
            "end_offset": 3,
            "type": "word",
            "position": 0
        },
        {
            "token": "quick",
            "start_offset": 4,
            "end_offset": 9,
            "type": "word",
            "position": 1
        },
        ...
    ]
}

标准分析器

标准分析器是 Elasticsearch 默认使用的分析器,根据 Unicode 联盟定义的单词边界划分文本,英文按照空格拆分,中文按照单汉字拆分,删除绝大部分标点。

POST _analyze

{
  "analyzer": "standard",
  "text":     "所有的光鲜,都有加班的味道"
}

# 输出

{
    "tokens": [
        {
            "token": "所",
            "start_offset": 0,
            "end_offset": 1,
            "type": "",
            "position": 0
        },
        {
            "token": "有",
            "start_offset": 1,
            "end_offset": 2,
            "type": "",
            "position": 1
        },
        {
            "token": "的",
            "start_offset": 2,
            "end_offset": 3,
            "type": "",
            "position": 2
        },
        {
            "token": "光",
            "start_offset": 3,
            "end_offset": 4,
            "type": "",
            "position": 3
        },
        {
            "token": "鲜",
            "start_offset": 4,
            "end_offset": 5,
            "type": "",
            "position": 4
        },
        {
            "token": "都",
            "start_offset": 6,
            "end_offset": 7,
            "type": "",
            "position": 5
        },
        ...
    ]
}

给索引指定分析器

创建索引时可指定分析器,加入的文档就会按照这个分词器进行分词保存。

PUT  /account
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english_analyzer": {
          "type": "standard",
          "max_token_length": 5,
          "stopwords": "_english_"
        }
      }
    }
  }
}

对于已经存在的索引,如何给索引加分析器呢?

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html

IK分析器

标准分析器不适用于中文分词,因为中文只有一个个词语组织在一起才有意义,单个汉字没什么意义,所有就有了专业的中文分析器。

IK 分析器是一款结合了词典和文法分析算法的中文分词组件,基于字符串匹配,支持用户词典扩展定义,支持细粒度和智能切分。

安装插件

使用插件命令安装中文分词IK插件,注意选择ES对应的版本,我这里选择的是7.0

sudo ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.0.0/elasticsearch-analysis-ik-7.0.0.zip

IK分析器的两种分析器分别叫:ik_smart (智能切分), ik_max_word(细粒度)

测试分词

POST /_analyze

{
  "analyzer": "ik_smart",
  "text":     "996都有加班的味道"
}

# 返回
{
    "tokens": [
        {
            "token": "996",
            "start_offset": 0,
            "end_offset": 3,
            "type": "ARABIC",
            "position": 0
        },
        {
            "token": "都有",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "加班",
            "start_offset": 5,
            "end_offset": 7,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "的",
            "start_offset": 7,
            "end_offset": 8,
            "type": "CN_CHAR",
            "position": 3
        },
        {
            "token": "味道",
            "start_offset": 8,
            "end_offset": 10,
            "type": "CN_WORD",
            "position": 4
        }
    ]
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html

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

https://github.com/medcl/elasticsearch-analysis-ik/blob/master/README.md

有问题可以扫描二维码和我交流

关注公众号「Python之禅」,回复「1024」免费获取Python资源