Elasticsearch:Text analysis
概述#
Text analysis(分词)使Elasticsearch在执行全文搜索时,不仅可以精确匹配搜索项,还能够返回与其相关的所有结果。 举例来说,如果一个索引中有以下几个文档:
- A quick brown fox jumps over the lazy dog
- fast fox
- foxes leap
当我们搜索Quick fox jumps
,我们很可能希望搜索结果中包含了上述文档,因为它们都与搜索项有着密切的关系:包含、复数和同义词。这便是分词器存在的价值,它让Elasticsearch的搜索结果更加符合使用者的预期。
组成#
在Elasticsearch中可以通过内置分词器实现分词,也可以按需定制分词器。 分词器由三部分组成:
Character Filters#
Character Filters将原始文本作为字符流接受并进行处理,它的作用是整理字符串。例如将印度-阿拉伯数字 (٠١٢٣٤٥٦٧٨٩)转化为阿拉伯-拉丁数字(0123456789)、去除HTML元素、将&转化为and等。一个分词器可以有0个或多个Character Filters,多个Character Filters的加载是有顺序的。
Tokenizer#
Tokenizer将字符流按照给定的规则切分为Token(可以看作为单词)。比如whitespace分词器在遇到空格和标点的时候,会将文本进行拆分。同时,Tokenizer还会记录每个Token在文本中的位置(position)、占位长度(positionLength)以及首尾字符的偏移量(start_offset/end_offset)。下图中每个Token的positionLength都为1,position分别为0、1和2:
与Character Filters不同的是,每个分词器有且仅有一个Tokenizer。
Token Filters#
Token Filters接收切分后的Token流并对Token进行加工,如小写(lowercase token filter),删除a,and和the等stopwords(stop token filter),增加同义词(synonym token filter),词根处理(Stemming)等。Token Filters并不会改变Token的位置,也不会改变其字符的偏移量。如下图所示,quick和它的同义词fast具有相同的position和positionLength:
而对于domain name system和它的的同义词dns来说,它们的postion都为0,但positionLength分别为1和3:
一个分词器可以有0个或多个Token Filters,多个Token Filters的加载是有顺序的。
应用场景#
分词器的应用场景有两个:文档被索引时(Index time)和文档被搜索时(Search time)。
- Index time:当一个文档被索引时,所有类型为text的字段的值都会被分词;
- Search time:当对类型为text的字段进行全文搜索时,搜索项将被分词。
因此,我们可以根据分词器应用场景的不同,将其分为索引分词器(index analyzer)和搜索分词器(search analyzer)两种。在大多数情况下,应当在索引和搜索时使用同样的分词器。这样可以保证索引中的字段值和查询项被分词为相同形式的Token,从而使查询结果更加符合我们的预期。
配置#
测试分词器#
可以使用analyze API来测试分词器对文本的处理情况,以一个内置的分词为例:
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
},
{
"token": "brown",
"start_offset": 10,
"end_offset": 15,
"type": "word",
"position": 2
},
{
"token": "fox.",
"start_offset": 16,
"end_offset": 20,
"type": "word",
"position": 3
}
]
}
当然也可以测试0个或多个Character Filters、一个Tokenizer和0个或多个Token Filters的组合效果:
POST _analyze
{
"tokenizer": "standard",
"filter": [ "lowercase", "asciifolding" ],
"text": "Is this déja vu?"
}
配置内置分词器#
我们可以对内置分词进行修改,从而让其实现我们想要的分词效果。例如,创建一个基于standard analyzer的分词器std_english,它可以在分词时删除英文中的a,and和the等stopwords:
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"std_english": {
"type": "standard", // type为standard(或simple、Whitespace等)表示基于内置的分词器
"stopwords": "_english_"
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "std_english"
}
}
}
}
}
}
索引的Mapping中规定,对my_text
字段使用standard analyzer分词,而my_text.english
字段则使用std_english。通过analyze API进行测试:
POST my-index-000001/_analyze
{
"field": "my_text",
"text": "The old brown cow"
}
POST my-index-000001/_analyze
{
"field": "my_text.english",
"text": "The old brown cow"
}
创建自定义分词器#
自定义分词器和所有分词器一样,都拥有一个Tokenizer,0个或多个Character Filters和0个或多个Token Filters,对应的字段分别为tokenizer
、char_filter
和filter
。除此之外,还可以通过定义position_increment_gap
字段来确保查询项是一个词组时不会与不同数组中的两个元素发生匹配。例如:
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
}
}
POST my-index-000001/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "Is this <b>déjà vu</b>?"
}
文本Is this <b>déjà vu</b>?
在索引到文档中后将会变成:[ is, this, deja, vu ]
。
指定分词器#
上文提到,根据应用场景的不同,我们将分词器分为了索引分词器(index analyzer)和搜索分词器(search analyzer)。Elasticsearch在确定需要使用的索引分词器前会依次检查以下参数,
- 索引中某一text字段的
analyzer
参数
PUT my-index-000001
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace"
}
}
}
}
- 索引的
settings.analysis.analyzer.default
参数
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "simple"
}
}
}
}
}
- 若上述参数均未指定,则使用内置的standard analyzer。
而对于搜索分词器的指定,Elasticsearch则需要依次检查这些参数:
- 搜索请求中的
analyzer
参数
GET my-index-000001/_search
{
"query": {
"match": {
"message": {
"query": "Quick foxes",
"analyzer": "stop"
}
}
}
}
- 索引中某一text字段的
search_analyzer
参数
PUT my-index-000001
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace", // 索引时使用whitespace分词
"search_analyzer": "simple" // 搜索时使用simple分词
}
}
}
}
- 索引的
settings.analysis.analyzer.default_search
参数:
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "simple" // 索引时使用simple分词
},
"default_search": {
"type": "whitespace" // 搜索时使用whitespace分词
}
}
}
}
}
- 若上述参数均未指定,则使用内置的standard analyzer。
作者:koktlzz
出处:https://www.cnblogs.com/koktlzz/p/14521577.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现