文本分词的概念:
文本信息通过一定的规则进行拆解,分成独立的词项,便于搜索,基于分词之后的字符去检索。
es内置分词器:
|--------------------|--------|--------|---------------------------------|------------------|---------|
| 分词器名称 | 是否ES内置 | 是否需装插件 | 核心特点 | 适用场景 | 默认分词器标记 |
| standard(标准分词器) | 是 | 否 | ES默认分词器,按单词边界切分,英文自动转小写,中文单字拆分 | 默认英文场景,不适合中文业务 | ✅ 默认分词器 |
| simple(简单分词器) | 是 | 否 | 按非字母字符切割,仅保留字母,全部转小写 | 简单英文文本过滤场景 | ❌ |
| whitespace(空格分词器) | 是 | 否 | 仅按空格字符切分,不处理标点、不转大小写 | 空格分隔的纯文本场景 | ❌ |
| stop(停用词分词器) | 是 | 否 | 在simple基础上,自动过滤英文停用词(a/an/the等) | 英文全文检索,去除无意义停用词 | ❌ |
| keyword(关键词分词器) | 是 | 否 | 完全不分词,将整段文本作为一个词条 | 精准匹配、枚举值、标签类字段 | ❌ |
| pattern(正则分词器) | 是 | 否 | 基于正则表达式自定义分词规则,灵活度高 | 有特殊分隔规则的文本场景 | ❌ |
| language(多语言分词器) | 是 | 否 | 针对英语、法语等多语言优化,无好用的中文内置分词 | 英文等拼音语言文本检索 | ❌ |
| fingerprint(指纹分词器) | 是 | 否 | 生成文本指纹,用于去重、相似度检索、内容排重 | 文本去重、版权校验、相似内容匹配 | ❌ |
| classic(经典分词器) | 是 | 否 | 老式英文分词器,兼容ES旧版本,功能与standard类似 | 兼容旧版本ES的英文场景 | ❌ |
在上面的内置分词器中可以发现,内置的分词器中没有合适的中文分词器。
深入分词器组成
分词器(Analyzer) 是全文检索的核心基石,直接决定了检索的准确率、召回率与性能。你提到的「字符过滤器、此项分析器、此项转换器」是对分词器核心组成的初步认知,存在少量笔误,本文将以官方标准定义为基础,完整解析 ES 分词器的三大核心组件 :字符过滤器(Character Filter) 、分词器(Tokenizer) 、词项过滤器(Token Filter),拆解各组件的职责、执行逻辑、内置实现与实战用法,帮你彻底吃透 ES 分词器的底层原理。
字符过滤器(Character Filter)
字符过滤器是分词器的前置预处理组件 ,作用于原始文本流,在文本被切分成词项之前,对单个字符进行清洗、转换、过滤、替换操作,从源头优化文本质量,为后续的分词切分做准备。
ES 内置常用字符过滤器
| 过滤器名称 | 核心功能 | 适用场景 |
|---|---|---|
html_strip |
剥离 HTML 标签,保留标签内的纯文本 | 网页内容、富文本日志、带 HTML 标签的业务文本 |
mapping |
自定义字符映射替换,支持批量字符替换 | 特殊符号清洗、全角 / 半角转换、敏感词替换 |
pattern_replace |
基于正则表达式的字符替换 | 复杂规则的文本清洗、固定格式的内容过滤 |
lowercase |
全量字符转小写(部分分词器内置,可单独配置) | 英文文本统一大小写,避免大小写导致的检索差异 |
示例:字符过滤器的实际效果
原始文本:<p>Hello World! 我是ES用户,123456</p> 经过 html_strip 字符过滤器处理后,输出:Hello World! 我是ES用户,123456 再经过 pattern_replace 过滤器(正则过滤数字)处理后,输出:Hello World! 我是ES用户,
代码展示:
GET _analyze
{
"char_filter": [
"html_strip"
],
"text": [
"<p>Hello World! 我是ES用户,123456</p>"
]
}
上文中为大家介绍了html的字符过滤器,下面为大家展示一下mapping的使用方式:
GET _analyze
{
"char_filter": [
{
"type": "mapping",
"mappings": [
"a=>1",
"b=> 2"
]
}
],
"text": [
"Ab shijian shijian"
]
}
分词器/切词器(Tokenizer)
整个文本分析的核心环节 :接收经过字符过滤后的文本,按照规则切割成一个个独立的词条(Token),同时记录每个词条的起始偏移、位置、类型等信息。
ES 自带多款开箱即用的 Tokenizer
ES 自带多款开箱即用的 Tokenizer,分为结构化分词、文本分词、语义分词三大类,下面逐个介绍用途、适用场景。
1. standard 标准分词器
- 规则 :基于Unicode 文本分割算法,按单词边界切分,以空格、标点作为分割依据;
- 特点 :默认忽略标点,适合英文、拉丁文;对中文不友好,会把每个汉字单独切成一个词;
- 适用场景:英文文档、国际化文本、普通外文检索。
2. whitespace 空格分词器
- 规则 :只按空格切割 ,遇到空格就拆分,不处理标点、不特殊过滤;
- 特点:标点会跟着单词一起保留,不做大小写转换;
- 适用场景:固定格式标签、编码、账号、带符号的英文短句。
3. keyword 关键词分词器
- 规则 :不做任何切分 ,把整个输入文本当作一个完整词条;
- 特点:原样保留内容,无拆分;
- 适用场景:精确匹配字段,如手机号、身份证、订单号、枚举状态、分类标签、主键 ID。
4. letter 字母分词器
- 规则 :连续字母组成一个词条,遇到非字母就切割;
- 特点:自动剔除数字、标点、特殊符号,只保留字母组合;
- 适用场景:纯英文词汇、单词检索,不需要数字和符号参与检索的场景。
5. pattern 正则表达式分词器
- 规则 :通过自定义正则表达式分割文本;
- 特点:高度灵活,可以自己定义分隔符规则;
- 适用场景:自定义分隔规则,如按逗号、下划线、横杠分割日志、结构化字符串。
6. simple 简单分词器
- 规则:遇到非字母字符就分割,只保留连续字母;
- 和 letter 区别:内部逻辑更轻量化,自动丢弃数字和符号,只切纯字母单词。
7. path_hierarchy 路径层级分词器
- 规则:针对文件路径、目录层级逐层拆分;
- 示例 :
/usr/local/elasticsearch拆分出:/usr、/usr/local、/usr/local/elasticsearch - 适用场景:文件路径、目录结构、分类层级、URL 路径检索。
8. ngram /edge_ngram 边缘分词器
ngram
按指定字符长度范围,滑动截取子串 ; 例:abc 长度 1~2:a、b、c、ab、bc。
edge_ngram
从字符串开头 固定截取前缀子串; 例:abc 长度 1~2:a、ab。
- 适用场景 :搜索框输入联想、自动补全、拼音模糊检索、短文本模糊匹配。
9. uax_url_email 网址邮箱分词器
- 规则 :智能识别 URL、邮箱,把完整网址、邮箱当作一个词条,不被标点拆分;
- 适用场景:内容包含网址、邮箱地址的文章、评论、留言检索。
使用代码展示:
java
GET _analyze
{
"text": [
"SHijian shi "
],
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
词项过滤器(Token Filter)
分词之后执行,对切分好的词条做二次加工:转小写、移除停用词、同义词替换、拼音转换、词干还原等。
下面展示了将分词之后的此项进行转化为小写
java
GET _analyze
{
"text": [
"SHijian shi "
],
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
自定义分词器实战:
下面的案例中,展示了自定义分词器和查询的DSL:
java
PUT /test_analyzer
{
"settings": {
"analysis": {
"analyzer": {
"study_analyzer": {
"type": "custom",
"char_filter": [],
"tokenizer": "standard",
"filter": [
"uppercase"
]
}
}
},
"number_of_replicas": 0
},
"mappings": {
"properties": {
"content":{
"type": "text",
"analyzer": "study_analyzer"
}
}
}
}
PUT test_analyzer/_doc/1
{
"content":"shijie nihao"
}
GET test_analyzer/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": {
"query": "shijie"
}
}
}
]
}
}
}
存数据用这个分词器,查数据自动也用这一个,不用额外配置,日常开发够用。
同时写
analyzer+search_analyzer
analyzer:存索引的时候用这套分词规则
search_analyzer:搜索查询的时候换另一套分词规则只有一种场景:入库分词 和 搜索分词 不想用一样的 ,才需要单独配
search_analyzer;
在指定的索引下测试自定义的分词器
java
POST /你的索引名/_analyze
{
"analyzer": "你在索引里定义的分词器名称",
"text": "要测试的文本"
}
安装和使用IK分词器:
- 下面展示的是使用物理主机的形式安装的es中的服务器安装Ik分词器。
- 在github中下载对应的版本:Index of: analysis-ik/stable/
- 下载之后将文件放到:/elasticsearch-8.5.2/plugins 文件中
- 之后执行解压缩命令:unzip elasticsearch-analysis-ik-8.5.2.zip -d ./ik
- 之后在重启es服务器就行了。
- 重启之后,使用下面的命令展示当前集群中的插件:
GET _cat/plugins?v
java
//使用的案例
PUT ik_text
{
"settings": {
"number_of_replicas": 0
},
"mappings": {
"properties": {
"content":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
PUT ik_text/_doc/1
{
"content":"今天是周日"
}
POST _analyze
{
"analyzer": "ik_max_word",
"text": [
"今天是周日,但是你为什么没有放假呢"]
}
POST _analyze
{
"analyzer": "ik_smart",
"text": [
"今天是周日,但是你为什么没有放假呢"]
}
两个分词器区别(超级简单)
- ik_max_word:拆得最细(适合存数据、检索)
- ik_smart:拆得粗、最少(适合搜索查询)
99% 项目直接用 ik_max_word 就够了!