一、题目
在集群上有一个索引task_new,brand字段match搜索 'Yoo-Hoo' 有3个,match搜索 'YooHoo' 有10个,请重建它到task_new 索引上,并满足以下要求:
集群一的 brand 字段包含关键字 'Yoo-Hoo' 和 'YooHoo',不管搜索 'yoohoo' 还是 'yoo-hoo',它的结果应该一样,都是3个。
task_new 和 task 的 doc 和 mapping 一样,mapping 要拷贝,不能直接 reindex
POST task/_doc/1
{"title":"Yoo-Hoo"}
POST task/_doc/2
{"title":"YooHoo"}
二、思考
通过分析题目,我们发现要查询两个不同的值都可以搜索到,主要是通过自定义分词进行实现。实现前先来了解一下自定义分词器的标准结构。
自定义分词包括三个部分,执行顺序从上到下为。
1、character filter 字符过滤器
- 作用:原始文本作为字符流接收,并通过添加、删除或更改字符来转换字符流
- 包括:html_strip(html标签过滤)、mapping(字符映射)、pattern_replace(正则匹配)
- 限制:数组类型,可以有0~n个
例如:<p>I'm a :) person, and you?</p> 文档为未分词前,在执行过character filter后通过html
2、tokenizer 分词切分器
- 作用:tokenizer 负责在接收字符流后对文本分词
- 包括:常用包括 whitespace(空格切分)、keyword(不做切分)、standard(基于Unicode切分)、lowercase(分词后转为小写)
- 限制:仅1个
3、token filter 分词过滤器
- 作用:对tokenizer处理后的字符流进行过滤处理,如:转换为小写、删除(去除停用词)等
- 包括:常用包括 stop(停止词过滤)、synonym(同义词过滤)
- 限制:数组类型,可以有0~n个
通过以上对自定义分词简单介绍,发现可以使用两种方式解答,1)character filter 字符过滤器中配置mapping对字符进行映射处理;2)token filter 分词过滤器中配置synonym同义词过滤字符
三、解题
初始化索引task
# DELETE task
# 初始化索引 task
PUT task
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 1
},
"mappings": {
"properties": {
"title":{
"type": "text"
}
}
}
}
# 初始化数据
POST task/_doc/1
{"title":"Yoo-Hoo"}
POST task/_doc/2
{"title":"YooHoo"}
方案一:character filter 中配置 mapping
Step 1、创建自定义分词、字段指定自定义分词
这里character filter 类型为 mapping类型,通过指定mapping 将下滑线指定为空。
mapping中指定 text 类型字段的 analyzer 为创建的自定义分词"mapping_analyzer"
# DELETE task_new
PUT task_new
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 1,
"analysis": {
"analyzer": {
"mapping_analyzer": {
"char_filter": [
"my_mapping"
],
"tokenizer": "whitespace",
"filter": [
"lowercase"
]
}
},
"char_filter": {
"my_mapping": {
"type": "mapping",
"mappings": [
"- => "
]
}
},
"tokenizer": {},
"filter": {}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "mapping_analyzer"
}
}
}
}
Step 2、执行reindex操作将数据导入task_new 索引
POST _reindex
{
"source": {
"index": "task"
},
"dest": {
"index": "task_new"
}
}
Step 3、执行查询语句
POST task_new/_search
{
"query": {
"match": {
"title": "Yoo-Hoo"
}
}
}
方案二:token filter 中配置 synonym
Step 1、创建自定义分词、字段指定自定义分词
创建自定义filter,命名为"my_synonym",使用同义词filter类型,并定义相关同义词,在mapping中自定义分词中filter指定my_synonym
#DELETE task_new
PUT task_new
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 1,
"analysis": {
"analyzer": {
"mapping_analyzer": {
"char_filter": [],
"tokenizer": "whitespace",
"filter": [
"lowercase","my_synonym"
]
}
},
"char_filter": {
},
"tokenizer": {},
"filter": {
"my_synonym":{
"type": "synonym",
"synonyms": [ "Yoo-Hoo, YooHoo => YooHoo" ]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "mapping_analyzer"
}
}
}
}
Step 2、3 同方案一
四、总结
1)自定义分词重点要记自定义分词器的标准结构,三个模块:character filter,tokenizer,filter 各各自的作用、数量限制、下面常用的类型。
2)例如:character filter 常用mapping,filter常用 synonym
3)注意自定义分词只能用在字段为text上,keyword 不可以的。
参考资料
- Text analysis | Elasticsearch Guide [8.1] | Elastic
- Create a custom analyzer | Elasticsearch Guide [8.1] | Elastic
送一波福利:
福利一
有需要内推JD的同学,可以私信或留言,我帮您内推,流程快!!!
有需要内推JD的同学,可以私信或留言,我帮您内推,流程快!!!
有需要内推JD的同学,可以私信或留言,我帮您内推,流程快!!!
福利二