ElasticSearch - 分词器
# 1. 什么是分词器(Analyzer)
分词器(Analyzer)是 Elasticsearch 中用于将文本数据转换为一系列词项(Token)的组件。分词器不仅会将文本拆分为小的词项,还会对词项进行标准化处理,比如将文本转换为小写、去除停用词、进行词干提取等。
分词器的主要功能:
将文本分割成独立的词项,以便进行快速的全文检索。分词器会对文本进行切割,生成多个词项,每个词项会指向包含它的文档。这种分割使得倒排索引(Inverted Index)能够高效地进行查询。
对词项进行标准化,比如大小写转换、去除停用词等。这保证了文本的统一性和可检索性。
分词器的组成:
一个分词器由以下三个主要组件组成:
字符过滤器(Character Filter):
在分词之前,首先通过字符过滤器对文本进行预处理。常见操作包括去除 HTML 标签、替换字符等。例如,将 HTML 标签<br>
替换为空格。分词器(Tokenizer):
核心组件,它将经过预处理的文本切分成一个个词项(Token),决定了文本是如何被拆分的。词项过滤器(Token Filter):
在分词完成后,词项过滤器对生成的词项进一步处理,比如将词项转换为小写、去除停用词或执行同义词替换。
# 2. 分词器的组成及作用
# 2.1 字符过滤器(Character Filters)
字符过滤器的作用是在分词之前预处理文本。它们可以对文本中的字符进行转换或过滤,确保分词器接收到的文本已经被清理和预处理。
- 常见字符过滤器:
html_strip
: 过滤掉 HTML 标签。mapping
: 将某些字符映射为其他字符(例如,将&
映射为and
)。
示例:将 <br>
标签转换为空格的字符过滤器。
{
"char_filter": {
"type": "html_strip"
}
}
2
3
4
5
# 2.2 分词器(Tokenizer)
分词器将文本切分为多个词项(Token),每个词项可以代表一个单词或短语。分词器的不同之处在于它们处理不同语言或结构的文本方式不同。
- 常见分词器:
standard
: 按空格、标点符号等拆分文本,并将所有字符转换为小写。whitespace
: 仅按空格拆分,不转换大小写。keyword
: 不进行任何拆分,直接将整个文本作为一个词项。
示例:将文本按空格和标点符号分割的 standard
分词器。
{
"tokenizer": {
"type": "standard"
}
}
2
3
4
5
# 2.3 词项过滤器(Token Filters)
词项过滤器对分词器生成的词项进行进一步的处理,可以修改词项、去除某些词项或增加同义词等。
- 常见词项过滤器:
lowercase
: 将所有词项转换为小写。stop
: 移除停用词(例如 "a", "the", "and")。synonym
: 将同义词替换为指定的词项。
示例:将所有词项转换为小写的词项过滤器。
{
"filter": {
"type": "lowercase"
}
}
2
3
4
5
# 3. 内置分词器及其测试
# 3.1 标准分词器(Standard Analyzer)
- 描述:这是 Elasticsearch 的默认分词器。它会将文本按照空格、标点符号等进行分割,同时将所有英文字符转换为小写,并去除标点符号。
- 适用场景:适用于英文文本的全文搜索和大多数语言的多语言处理。
示例:使用标准分词器分析文本
POST /_analyze
{
"analyzer": "standard", // 使用标准分词器
"text": "I love Elasticsearch. It's amazing!"
}
2
3
4
5
分词结果解析:
{
"tokens": [
{ "token": "i", "start_offset": 0, "end_offset": 1, "type": "<ALPHANUM>", "position": 0 },
{ "token": "love", "start_offset": 2, "end_offset": 6, "type": "<ALPHANUM>", "position": 1 },
{ "token": "elasticsearch", "start_offset": 7, "end_offset": 20, "type": "<ALPHANUM>", "position": 2 },
{ "token": "it", "start_offset": 22, "end_offset": 24, "type": "<ALPHANUM>", "position": 3 },
{ "token": "s", "start_offset": 25, "end_offset": 26, "type": "<ALPHANUM>", "position": 4 },
{ "token": "amazing", "start_offset": 27, "end_offset": 34, "type": "<ALPHANUM>", "position": 5 }
]
}
2
3
4
5
6
7
8
9
10
字段说明:
- token:这是分词后的词项。例如,
"i"
、"love"
、"elasticsearch"
是从文本中提取出来的词项。 - start_offset 和 end_offset:这些字段指示了词项在原始文本中的起始位置和结束位置。例如,词项
"love"
从文本的第 2 个字符开始,到第 6 个字符结束。 - type:词项的类型,
<ALPHANUM>
表示这是字母或数字类型的词项。 - position:词项的相对位置。例如,词项
"love"
的位置是 1,表示这是文本中的第二个词项。
# 3.2 简单分词器(Simple Analyzer)
- 描述:简单分词器将文本按空格和标点符号进行分割,同时将所有字符转换为小写,并去除标点符号。
- 适用场景:适合对英文文本进行简单分词处理。
示例:使用简单分词器分析文本
POST /_analyze
{
"analyzer": "simple", // 使用简单分词器
"text": "I love Elasticsearch. It's amazing!"
}
2
3
4
5
分词结果解析:
{
"tokens": [
{ "token": "i", "start_offset": 0, "end_offset": 1, "type": "<ALPHANUM>", "position": 0 },
{ "token": "love", "start_offset": 2, "end_offset": 6, "type": "<ALPHANUM>", "position": 1 },
{ "token": "elasticsearch", "start_offset": 7, "end_offset": 20, "type": "<ALPHANUM>", "position": 2 },
{ "token": "it", "start_offset": 22, "end_offset": 24, "type": "<ALPHANUM>", "position": 3 },
{ "token": "s", "start_offset": 25, "end_offset": 26, "type": "<ALPHANUM>", "position": 4 },
{ "token": "amazing", "start_offset": 27, "end_offset": 34, "type": "<ALPHANUM>", "position": 5 }
]
}
2
3
4
5
6
7
8
9
10
# 3.3 空白分词器(Whitespace Analyzer)
- 描述:空白分词器根据空格来分割文本,不对字符大小写进行转换,也不会移除标点符号。
- 适用场景:适用于对源代码、URL、文件路径等敏感字符进行处理的场景。
示例:使用空白分词器分析文本
POST /_analyze
{
"analyzer": "whitespace", // 使用空白分词器
"text": "I love Elasticsearch. It's amazing!"
}
2
3
4
5
分词结果解析:
{
"tokens": [
{ "token": "I", "start_offset": 0, "end_offset": 1, "type": "word", "position": 0 },
{ "token": "love", "start_offset": 2, "end_offset": 6, "type": "word", "position":
1 },
{ "token": "Elasticsearch.", "start_offset": 7, "end_offset": 21, "type": "word", "position": 2 },
{ "token": "It's", "start_offset": 22, "end_offset": 26, "type": "word", "position": 3 },
{ "token": "amazing!", "start_offset": 27, "end_offset": 35, "type": "word", "position": 4 }
]
}
2
3
4
5
6
7
8
9
10
11
说明:
- 这里每个词项按照空格切分,标点符号不会被移除,例如
"Elasticsearch."
和"amazing!"
中的标点符号保留了下来。
# 3.4 关键字分词器(Keyword Analyzer)
- 描述:关键字分词器不进行任何分词操作,会将整个输入文本作为一个词项。适用于需要精确匹配的场景,例如处理 URL、电子邮件地址或某些标识符。
- 适用场景:适合需要精确匹配的场景,如 URL、标识符、序列号等。
示例:使用关键字分词器分析文本
POST /_analyze
{
"analyzer": "keyword", // 使用关键字分词器
"text": "I love Elasticsearch. It's amazing!"
}
2
3
4
5
分词结果解析:
{
"tokens": [
{ "token": "I love Elasticsearch. It's amazing!", "start_offset": 0, "end_offset": 35, "type": "word", "position": 0 }
]
}
2
3
4
5
说明:
- 整个输入文本
"I love Elasticsearch. It's amazing!"
被作为一个词项,没有进行分割。
# 4. 创建索引时如何指定分词器
在创建索引时,可以为特定的字段指定一个分词器。Elasticsearch 默认使用 standard
分词器,但可以通过 analyzer
参数来指定其他分词器。
示例:创建一个指定分词器的索引
PUT /my_index
{
"settings": {},
"mappings": {
"properties": {
"title": {
"type": "text", // 定义字段类型为 text
"analyzer": "standard" // 指定使用标准分词器
},
"description": {
"type": "text", // 定义字段类型为 text
"analyzer": "whitespace" // 使用空白分词器
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在此示例中,title
字段使用标准分词器,而 description
字段使用空白分词器。这样你可以为不同字段选择合适的分词器。
# 5. 中文分词器(IK 分词器)
IK
分词器是 Elasticsearch 中最常用的开源中文分词插件,支持中文的细粒度和粗粒度分词。它广泛应用于中文文本处理,如搜索、分析和文本挖掘。
IK 分词器的两种分词模式:
ik_smart:粗粒度分词模式,将文本拆分为最少量的有意义的词项。例如“中华人民共和国国歌”被分为两个词项:“中华人民共和国”和“国歌”。
ik_max_word:细粒度分词模式,文本被拆分为尽可能多的词项,适用于复杂文本。例如“中华人民共和国国歌”会被拆分为多个词项:“中华”,“中华人民”,“中华人民共和国”,“国歌”等。
# 5.1 安装 IK 分词器
# 1. 传统安装方式
下载 IK 分词器插件
访问 IK 分词器的 GitHub 仓库 (opens new window),选择与你的 Elasticsearch 版本匹配的分词器版本,并下载。
例如,对于 Elasticsearch 7.14 版本,执行以下命令下载对应的 IK 插件:
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.0/elasticsearch-analysis-ik-7.14.0.zip
1解压插件并移动到 Elasticsearch 插件目录
unzip elasticsearch-analysis-ik-7.14.0.zip mv elasticsearch-analysis-ik /usr/share/elasticsearch/plugins/
1
2/usr/share/elasticsearch/plugins/
:这是 Elasticsearch 的插件目录,你需要将解压后的elasticsearch-analysis-ik
插件移动到该目录下。
重启 Elasticsearch
安装插件后,你需要重启 Elasticsearch 服务,使插件生效。
sudo systemctl restart elasticsearch
1验证插件是否安装成功
在浏览器或使用
curl
命令访问以下 URL,验证插件是否安装成功:curl -X GET "localhost:9200/_cat/plugins?v"
1如果返回的插件列表中包含
elasticsearch-analysis-ik
,则表示 IK 分词器安装成功。
# 2. Docker 安装方式
# 2.1 在ES 容器内安装 IK 分词器
1. 下载并解压 IK 分词器插件
首先,我们需要下载与你的 Elasticsearch 版本相匹配的 IK 分词器插件,并解压到本地目录中。以下命令示例中下载的是 7.14.0 版本的插件。
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.0/elasticsearch-analysis-ik-7.14.0.zip
unzip elasticsearch-analysis-ik-7.14.0.zip -d elasticsearch-analysis-ik/
2
wget
命令用于下载 IK 分词器插件的压缩包。unzip
命令将下载的插件包解压到名为elasticsearch-analysis-ik
的目录中。- 注意:确保下载的插件版本与 Elasticsearch 的版本相匹配,否则插件可能无法正常工作。
2. 将插件移动到 Elasticsearch 容器中
Elasticsearch 容器中的插件存储目录位于 /usr/share/elasticsearch/plugins/
。我们需要将解压后的 IK 分词器插件移动到该目录下。可以通过 docker cp
命令将本地解压后的插件复制到运行中的 Elasticsearch 容器中。
docker cp elasticsearch-analysis-ik/ <es_container_id>:/usr/share/elasticsearch/plugins/
docker cp
命令用于将本地目录复制到容器内部。<es_container_id>
是你的 Elasticsearch 容器的名称或容器 ID,你可以通过docker ps
命令获取运行中的容器 ID。- 该命令将解压后的
elasticsearch-analysis-ik
插件复制到容器的/usr/share/elasticsearch/plugins/
目录下。插件目录名可以自定义,Elasticsearch 会自动读取插件目录中的内容并加载。
3. 重启 Elasticsearch 容器
在完成插件的复制后,需要重启 Elasticsearch 容器以使 IK 分词器生效。使用以下命令重启容器:
docker restart <es_container_id>
<es_container_id>
是 Elasticsearch 容器的名称或容器 ID。- 该命令会立即停止并重新启动容器,使插件生效。
4. 验证 IK 分词器是否安装成功
要确认 IK 分词器插件是否成功安装,可以通过以下 curl
命令查看已安装的插件列表:
curl -X GET "localhost:9200/_cat/plugins?v"
如果安装成功,输出中应该包含 elasticsearch-analysis-ik
插件的信息,类似如下所示:
name component version
es_node elasticsearch-analysis-ik 7.14.0
2
# 2.2 使用挂载方式安装 IK 分词器
另一种方式是通过将本地的插件目录挂载到容器内,这样可以避免每次更改插件时都需要重新构建或复制插件。
1. 准备本地插件目录
在本地创建一个插件目录,并将解压后的 IK 分词器插件复制到这个目录中。
mkdir -p /path/to/local/elasticsearch/plugins/ik
cp -r elasticsearch-analysis-ik/* /path/to/local/elasticsearch/plugins/ik
2
/path/to/local/elasticsearch/plugins/ik
是本地创建的插件目录,用于存放 IK 分词器插件的文件。cp -r
命令将解压后的 IK 分词器插件文件复制到本地插件目录中。- 注意:确保本地目录中的插件解压完整,并且目录结构保持一致。
2. 启动并挂载本地插件目录到容器
使用 docker run
命令启动 Elasticsearch 容器,并通过 -v
选项将本地插件目录挂载到容器内的插件目录中。这样 Elasticsearch 可以直接从挂载的本地目录中加载 IK 分词器。
docker run -d --name es_with_ik -p 9200:9200 -p 9300:9300 \
-v /path/to/local/elasticsearch/plugins/ik:/usr/share/elasticsearch/plugins/ik \
docker.elastic.co/elasticsearch/elasticsearch:7.14.0
2
3
-v /path/to/local/elasticsearch/plugins/ik:/usr/share/elasticsearch/plugins/ik
是挂载选项,将本地的 IK 插件目录挂载到容器内部的/usr/share/elasticsearch/plugins/ik
目录中。-d
表示后台运行容器。-p 9200:9200 -p 9300:9300
是端口映射,将容器的 9200 和 9300 端口映射到宿主机的对应端口。docker.elastic.co/elasticsearch/elasticsearch:7.14.0
是 Elasticsearch 官方镜像的版本。
3. 验证插件安装
同样,可以使用 curl
命令来验证 IK 分词器是否成功安装。
curl -X GET "localhost:9200/_cat/plugins?v"
你应该能看到类似以下的输出,表明 IK 分词器已经成功加载:
name component version
es_node elasticsearch-analysis-ik 7.14.0
2
# 5.2 使用 IK 分词器
IK 分词器提供了两种分词模式,分别是 ik_smart(粗粒度分词)和 ik_max_word(细粒度分词)。你可以根据需求选择合适的分词模式。
# 1. ik_smart 模式(粗粒度分词)
示例:使用 ik_smart
分词器对中文文本进行分词。
POST /_analyze
{
"analyzer": "ik_smart", // 使用 ik_smart 分词器
"text": "中华人民共和国国歌"
}
2
3
4
5
分词结果:
{
"tokens": [
{ "token": "中华人民共和国", "start_offset": 0, "end_offset": 7, "type": "CN_WORD", "position": 0 },
{ "token": "国歌", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 1 }
]
}
2
3
4
5
6
- 分词结果说明:
"token"
:表示分词后的词项,例如"中华人民共和国"
和"国歌"
。"start_offset"
和"end_offset"
:表示该词项在原始文本中的起始和结束位置。"type"
:词项类型,"CN_WORD"
表示中文词项。"position"
:词项在文本中的顺序位置。
# 2. ik_max_word 模式(细粒度分词)
示例:使用 ik_max_word
分词器对中文文本进行细粒度分词。
POST /_analyze
{
"analyzer": "ik_max_word", // 使用 ik_max_word 分词器
"text": "中华人民共和国国歌"
}
2
3
4
5
分词结果:
{
"tokens": [
{ "token": "中华人民共和国", "start_offset": 0, "end_offset": 7, "type": "CN_WORD", "position": 0 },
{ "token": "中华", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 1 },
{ "token": "华人", "start_offset": 1, "end_offset": 3, "type": "CN_WORD", "position": 2 },
{ "token": "国歌", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 3 }
]
}
2
3
4
5
6
7
8
- 分词结果说明:
ik_max_word
模式会对文本进行尽可能多的拆分。例如,“中华人民共和国”被分为了“中华”,“中华人民共和国”等多种组合,适合对文本进行更精细的分词处理。"token"
:表示分词后的词项。"start_offset"
和"end_offset"
:表示词项在原始文本中的位置。"type"
:表示词项类型。"position"
:词项在文本中的顺序。
# 5.3 IK 分词器的扩展词和停用词
IK 分词器支持用户自定义扩展词典和停用词典。通过修改配置文件,可以增加或去除特定的词项。
扩展词典
:就是有些词并不是关键词,但是也希望被ES用来作为检索的关键词,可以将这些词加入扩展词典。停用词典
:就是有些词是关键词,但是出于业务场景不想使用这些关键词被检索到,可以将这些词放入停用词典。
配置步骤:
找到 IK 分词器的配置文件
在plugins/analysis-ik/config
目录下找到并编辑IKAnalyzer.cfg.xml
文件:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 扩展配置</comment> <!-- 用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">ext_dict.dic</entry> <!-- 用户可以在这里配置自己的扩展停止词字典 --> <entry key="ext_stopwords">ext_stopword.dic</entry> </properties>
1
2
3
4
5
6
7
8
9定义扩展词典
在config
目录下,创建ext_dict.dic
文件,并在其中加入需要额外识别的词汇。每行一个词汇,文件编码格式必须为UTF-8
。示例:
大数据 人工智能 区块链
1
2
3定义停用词典
同样在config
目录下,创建ext_stopword.dic
文件,并加入不需要被搜索的停用词。每行一个停用词,文件编码格式必须为UTF-8
。示例:
是 的 和
1
2
3重启 Elasticsearch
修改完词典后,重启 Elasticsearch 服务以使新配置生效。