详解elasticsearch实现基于拼音搜索
作者:huan1993 发布时间:2022-12-06 04:23:04
1、背景
一般情况下,有些搜索需求是需要根据拼音和中文来搜索的,那么在elasticsearch
中是如何来实现基于拼音来搜索的呢?可以通过elasticsearch-analysis-pinyin
分析器来实现。
2、安装拼音分词器
# 进入 es 的插件目录
cd /usr/local/es/elasticsearch-8.4.3/plugins
# 下载
wget https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v8.4.3/elasticsearch-analysis-pinyin-8.4.3.zip
# 新建目录
mkdir analysis-pinyin
# 解压
mv elasticsearch-analysis-pinyin-8.4.3.zip analysis-pinyin && cd analysis-pinyin && unzip elasticsearch-analysis-pinyin-8.4.3.zip && rm -rvf elasticsearch-analysis-pinyin-8.4.3.zip
cd ../ && chown -R es:es analysis-pinyin
# 启动es
/usr/local/es/elasticsearch-8.4.3/bin/elasticsearch -d
3、拼音分词器提供的功能
拼音分词器提供如下功能
每个选项的含义 可以通过 文档中的例子来看懂。
4、简单测试一下拼音分词器
4.1 dsl
GET _analyze
{
"text": ["我是中国人"],
"analyzer": "pinyin"
}
"analyzer": "pinyin"
此处的pinyin
是拼音分词器自带的。
4.2 运行结果
从图片上,实现了拼音分词,但是这个不一定满足我们的需求,比如没有中文了,单个的拼音(比如:wo)是没有什么用的,需要对拼音分词器进行定制化。
5、es中分词器的组成
在elasticsearch
中分词器analyzer
由如下三个部分组成:
character filters:
用于在tokenizer
之前对文本进行处理。比如:删除字符,替换字符等。tokenizer:
将文本按照一定的规则分成独立的token。即实现分词功能。tokenizer filter:
将tokenizer
输出的词条做进一步的处理。比如: 同义词处理,大小写转换、移除停用词,拼音处理等。
6、自定义一个分词器实现拼音和中文的搜索
需求: 自定义一个分词器,即可以实现拼音搜索,也可以实现中文搜索。
1、创建mapping
PUT /test_pinyin
{
"settings": {
// 分析阶段的设置
"analysis": {
// 分析器设置
"analyzer": {
// 自定义分析器,在tokenizer阶段使用ik_max_word,在filter上使用py
"custom_analyzer": {
"tokenizer": "ik_max_word",
"filter": "custom_pinyin"
}
},
// 由于不满足pinyin分词器的默认设置,所以我们基于pinyin
// 自定义了一个filter,叫py,其中修改了一些设置
// 这些设置可以在pinyin分词器官网找到
"filter": {
"custom_pinyin": {
"type": "pinyin",
// 不会这样分:刘德华 > [liu, de, hua]
"keep_full_pinyin": false,
// 这样分:刘德华 > [liudehua]
"keep_joined_full_pinyin": true,
// 保留原始token(即中文)
"keep_original": true,
// 设置first_letter结果的最大长度,默认值:16
"limit_first_letter_length": 16,
// 当启用此选项时,将删除重复项以保存索引,例如:de的> de,默认值:false,注意:位置相关查询可能受影响
"remove_duplicated_term": true,
// 如果非汉语字母是拼音,则将其拆分为单独的拼音术语,默认值:true,如:liudehuaalibaba13zhuanghan- > liu,de,hua,a,li,ba,ba,13,zhuang,han,注意:keep_none_chinese和keep_none_chinese_together应首先启用
"none_chinese_pinyin_tokenize": false
}
}
}
},
// 定义mapping
"mappings": {
"properties": {
"name": {
"type": "text",
// 创建倒排索引时使用的分词器
"analyzer": "custom_analyzer",
// 搜索时使用的分词器,搜索时不使用custom_analyzer是为了防止 词语的拼音一样,但是中文含义不一样,导致搜索错误。 比如: 科技 和 客机,拼音一样,但是含义不一样
"search_analyzer": "ik_smart"
}
}
}
}
注意:可以看到 我们的 name
字段 使用的分词器是 custom_analyzer
,这个是我们在上一步定义的。但是搜索的时候使用的是 ik_smart
,这个为甚么会这样呢?
假设我们存在如下2个文本 科技强国和 这是一架客机, 那么科技和客机的拼音是不是就是一样的。 这个时候如果搜索时使用的分词器也是custom_analyzer
那么,搜索科技的时候客机也会搜索出来,这样是不对的。因此在搜索的时候中文就以中文搜,拼音就以拼音搜。
{
"name": {
"type": "text",
"analyzer": "custom_analyzer",
"search_analyzer": "ik_smart"
}
}
当 analyzer
和search_analyzer
的值都是custom_analyzer
,搜索时也会通过拼音搜索,这样的结果可能就不是我们想要的。
2、插入数据
PUT /test_pinyin/_bulk
{"index":{"_id":1}}
{"name": "科技强国"}
{"index":{"_id":2}}
{"name": "这是一架客机"}
{"index":{"_id":3}}
3、搜索数据
参考文档
1、github.com/medcl/elast…
来源:https://juejin.cn/post/7188728954012844069
猜你喜欢
- BeanPostProcessor接口作用:如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处
- 背景最近在探秘kafka为什么如此快?其背后的秘诀又是什么?怀着好奇之心,开始像剥洋葱 一样逐层内嵌。一步步揭晓kafka能够吊打mq的真因
- 本文实例为大家分享了Unity键盘WASD实现物体移动的具体代码,供大家参考,具体内容如下1首先在场景中建立一个Capsule,将主摄像机拖
- 在SpringMVC的入门学习中,我发现@GetMapping注解的使用要注意路径冲突问题,在网上都没找到类似我这样的情况,所以我在这里将问
- 1.DRUID连接池介绍Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面
- 项目背景我们开发过程中会碰到这样一类问题,就是数据层或三方接口返回的Bean对象需要转换重新装换一下我们需要的对象。我们通常的做法就是通过g
- 前言Java.util包中的List接口继承了Collection接口,用来存放对象集合,所以对这些对象进行排序的时候,要么让对象类自己实现
- ArrayList中存放引用数据类型ArrayList中存放引用类型时,存放的是一个引用,因此在放入ArrayList之后再进行改动会影响到
- SpringBoot 集成 activiti 基础环境搭建添加依赖<dependency> <groupId&g
- 配置多个别名 typeAliasesPackage<property name="typeAliasesPackage&qu
- 一、场景笔者就Zuul网关下实现其负载均衡与熔断机制(雪崩)进行实践,前提是已经导入zuul相关依赖springboot版本:1.5.9.R
- 当我们拿到一大段JSON字符串的时候,分析起来简直头皮发麻,相信很大一部分朋友也都会直接去BEJSON等网站去做一个JSON格式化,已方便自
- 前端页面功能模块化拆分当一个系统的功能很多时,不可能所有功能模块的页面都写在一个页面里面,这时就需要将不同功能模块的页面拆分出去,就像模板一
- Lombok有什么用在我们实体Bean中有大量的Getter/Setter方法以及toString, hashCode等可能不会用到,但是某
- 前言现如今几乎大多数Java应用,例如我们耳熟能详的tomcat, struts2, netty...等等数都数不过来的软件,要满足通用性,
- 1. 什么是 spring-boot-devtoolsspring-boot-devtools 是 spring-boot项目开发时的一个热
- public Bitmap CopyBitmap(Bitmap source){ int depth =
- 功能函数// 图像旋转void Rotate(const cv::Mat &srcImage, cv::Mat &dstIm
- 一、运行class文件执行带main方法的class文件,命令行为:java <CLASS文件名>注意:CLASS文件名不要带文
- 注册BeanPostProcessorrefresh()调用registerBeanPostProcessors(beanFactory)方