Elasticsearch自动补全

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项。

这种根据用户输入的字母,提示完整词条的功能,就是自动补全了。

因为需要根据拼音字母来推断,因此要用到拼音分词功能。

1、拼音分词器

要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:https://github.com/medcl/elasticsearch-analysis-pinyin

安装方式与IK分词器一样,分三步:

​ ①解压

​ ②上传到虚拟机中,elasticsearch的plugin目录

​ ③重启elasticsearch

​ ④测试

DSL测试如下
# 拼音分词器
POST /_analyze
{"text": "上海酒店还不错","analyzer": "pinyin"
}

拼音分词结果

{"tokens" : [{"token" : "shang","start_offset" : 0,"end_offset" : 0,"type" : "word","position" : 0},.......]
}

2、自定义分词器

默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。

elasticsearch中分词器(analyzer)的组成包含三部分:

  • character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
  • tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

文档分词时会依次由这三部分来处理文档:

声明自定义分词器的语法如下:
PUT /test
{"settings": {"analysis": {"analyzer": { // 自定义分词器"my_analyzer": {  // 分词器名称"tokenizer": "ik_max_word", // 普通分词器"filter": "py" // 拼音分词器}},"filter": { // 自定义tokenizer filter"py": { // 过滤器名称"type": "pinyin", // 过滤器类型,这里是 pinyin"keep_full_pinyin": false, // 单个字分词"keep_joined_full_pinyin": true, // 全拼"keep_original": true, // 保留中文"limit_first_letter_length": 16,"remove_duplicated_term": true,"none_chinese_pinyin_tokenize": false}}}},"mappings": {"properties": {"name": {"type": "text","analyzer": "my_analyzer", // 指定分词器(自定义)"search_analyzer": "ik_smart" // 指定搜索时不使用拼音}}}
}
自定义分词器测试

1、指定文本进行拆分

# 测试自定义分词器
POST /test/_analyze
{"text": "上海酒店还不错","analyzer": "my_analyzer"
}

测试结果

{"tokens" : [{"token" : "上海","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 0},{"token" : "shanghai","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 0}]
}

插入文档测试

# 测试自定义分词器
POST /test/_analyze
{"text": "上海酒店还不错","analyzer": "my_analyzer"
}POST /test/_doc/1
{"id": 1,"name": "狮子"
}
POST /test/_doc/2
{"id": 2,"name": "虱子"
}# 测试拼音搜索
GET /test/_search
{"query": {"match": {"name": "shizi"}}
}

上面的测试查询shizi因为插入的两个文档中都是同音的所以都会查询到两条数据

使用同音搜索结果测试

狮子与虱子是同音的搜索的时候也会出现虱子这就说明了自定义拼音分词器有问题,使用中文搜索也会将同音的搜索出来

# 测试拼音搜索
GET /test/_search
{"query": {"match": {"name": "掉入狮子笼咋办"}}
}
解决方案

拼音分词器适合在创建倒排序索引的时候使用,但不能在搜索时使用

因此字段在创建倒排序索引时应用my_analyzer分词器,字段在搜索时应该使用ik_smart分词器"search_analyzer": "ik_smart"

"mappings": {"properties": {"name": {"type": "text","analyzer": "my_analyzer", // 指定分词器(自定义)"search_analyzer": "ik_smart" // 指定搜索时不使用拼音}}}

指定之后,就不会出现出现同音的问题了

总结:

如何使用拼音分词器?

  • ①下载pinyin分词器

  • ②解压并放到elasticsearch的plugin目录

  • ③重启即可

如何自定义分词器?

  • ①创建索引库时,在settings中配置,可以包含三部分

  • ②character filter

  • ③tokenizer

  • ④filter

拼音分词器注意事项?

  • 为了避免搜索到同音字,搜索时不要使用拼音分词器"search_analyzer": "ik_smart"

3、自动补全查询

elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

  • 参与补全查询的字段必须是completion类型。

  • 字段的内容一般是用来补全的多个词条形成的数组。

比如,一个这样的索引库:

// 创建索引库
PUT test
{"mappings": {"properties": {"title":{"type": "completion"}}}
}

然后插入下面的数据:

// 示例数据
POST test/_doc
{"title": ["Sony", "WH-1000XM3"]
}
POST test/_doc
{"title": ["SK-II", "PITERA"]
}
POST test/_doc
{"title": ["Nintendo", "switch"]
}

查询的DSL语句如下:

// 自动补全查询
GET /test/_search
{"suggest": {"title_suggest": { // 自定义名称"text": "s", // 关键字"completion": { // 补全类型"field": "title", // 补全查询的字段"skip_duplicates": true, // 跳过重复的"size": 10 // 获取前10条结果}}}
}

自动补全示例

# 自动补全的索引库
PUT test2
{"mappings": {"properties": {"title":{"type": "completion"}}}
}
# 示例数据
POST test2/_doc
{"title": ["Sony", "WH-1000XM3"]
}
POST test2/_doc
{"title": ["SK-II", "PITERA"]
}
POST test2/_doc
{"title": ["Nintendo", "switch"]
}# 自动补全查询
POST /test2/_search
{"suggest": {"title_suggest": {"text": "s","completion": {"field": "title","skip_duplicates": true,"size": 10}}}
}

对关键字s的查询结果

4、实现酒店搜索框自动补全

现在,我们的hotel索引库还没有设置拼音分词器,需要修改索引库中的配置。但是我们知道索引库是无法修改的,只能删除然后重新创建。

另外,我们需要添加一个字段,用来做自动补全,将brand、suggestion、city等都放进去,作为自动补全的提示。

因此,总结一下,我们需要做的事情包括:

  1. 修改hotel索引库结构,设置自定义拼音分词器

  2. 修改索引库的name、all字段,使用自定义分词器

  3. 索引库添加一个新字段suggestion,类型为completion类型,使用自定义的分词器

  4. 给HotelDoc类添加suggestion字段,内容包含brand、business

  5. 重新导入数据到hotel库

4.1、修改酒店映射结构

# -------------酒店自动补全案例-----------# 查看索引库的结果
GET /hotel/_mapping# 删除原来的索引库
DELETE /hotel# 修改酒店索引库结构
PUT /hotel
{"settings": {"analysis": {"analyzer": {"text_anlyzer": {"tokenizer": "ik_max_word","filter": "py"},"completion_analyzer": {"tokenizer": "keyword","filter": "py"}},"filter": {"py": {"type": "pinyin","keep_full_pinyin": false,"keep_joined_full_pinyin": true,"keep_original": true,"limit_first_letter_length": 16,"remove_duplicated_term": true,"none_chinese_pinyin_tokenize": false}}}},"mappings": {"properties": {"id":{"type": "keyword"},"name":{"type": "text","analyzer": "text_anlyzer","search_analyzer": "ik_smart","copy_to": "all"},"address":{"type": "keyword","index": false},"price":{"type": "integer"},"score":{"type": "integer"},"brand":{"type": "keyword","copy_to": "all"},"city":{"type": "keyword"},"starName":{"type": "keyword"},"business":{"type": "keyword","copy_to": "all"},"location":{"type": "geo_point"},"pic":{"type": "keyword","index": false},"all":{"type": "text","analyzer": "text_anlyzer","search_analyzer": "ik_smart"},"suggestion":{"type": "completion","analyzer": "completion_analyzer"}}}
}

4.2、修改接收数据的HotelDoc实体类

HotelDoc中要添加一个字段,用来做自动补全,内容可以是酒店品牌、城市、商圈等信息。按照自动补全字段的要求,最好是这些字段的数组。

因此我们在HotelDoc中添加一个suggestion字段,类型为List<String>,然后将brand、city、business等信息放到里面。

package cn.itcast.hotel.pojo;import lombok.Data;
import lombok.NoArgsConstructor;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;@Data
@NoArgsConstructor
public class HotelDoc {...private List<String> suggestion;public HotelDoc(Hotel hotel) {// 组装suggestionif(this.business.contains("/")){// business有多个值,需要切割String[] arr = this.business.split("/");// 添加元素this.suggestion = new ArrayList<>();this.suggestion.add(this.brand);Collections.addAll(this.suggestion, arr);}else {this.suggestion = Arrays.asList(this.brand, this.business);}}
}

4.3、运行自动导入数据

重新执行之前编写的导入数据功能,可以看到新的酒店数据中包含了suggestion:

运行测试代码

4.4、自动补全查询的JavaAPI

之前我们学习了自动补全查询的DSL,而没有学习对应的JavaAPI,这里给出一个示例:

而自动补全的结果也比较特殊,解析的代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QMVTWXqV-1654397685637)(images/image-20220605102739780.png)]

4.5、控制器的编写

/*** 前端页面请求完成关键字查询* @param key* @return*/
@GetMapping("/suggestion")
public List<String> getSuggestion(@RequestParam("key") String key){return hotelService.getSuggestion(key);
}

4.5、业务层代码实现

接口的编写

List<String> getSuggestion(String key);

实现类

/*** 实现前端关键字搜索* @param key* @return*/
@Override
public List<String> getSuggestion(String key) {try {// 1、准备额requestSearchRequest request = new SearchRequest("hotel");// 2、准备DSLrequest.source().suggest(new SuggestBuilder().addSuggestion("suggestions",SuggestBuilders.completionSuggestion("suggestion").prefix(key).skipDuplicates(true).size(10)));// 3、发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析结果Suggest suggest = response.getSuggest();// 4.1.根据补全查询名称,获取补全结果CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");// 4.2.获取optionsList<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();// 4.3.遍历List<String> list = new ArrayList<>(options.size());for (CompletionSuggestion.Entry.Option option : options) {String text = option.getText().toString();list.add(text);}return list;} catch (IOException e) {throw new RuntimeException(e);}
}
4.6、接口的测试

Elasticsearch自动补全(拼音查询自动补全)相关推荐

  1. php 0补全,PHP给数字或字符串补零0或自动补全其他符号

    PHP给数字或字符串补零0或自动补全其他符号 2014-04-10 在php中有两个函数--至少有两个是否有其他的我还不知道,能够实现数字补零,str_pad(),sprintf()详细如下 一.st ...

  2. 12C 新特性 | 标量子查询自动转换

    有超过6年超大型数据库专业服务经验,擅长数据库解决方案设计与项目管理:在多年的技术实践中,先后为运营商(移动.电信).银行.保险.制造业等各行业客户的业务关键型系统提供了运维.升级.性能优化.项目实施 ...

  3. Py:利用pyautogui实现自动将pdf文件(需手动设定pdf总页数)自动翻页并截取另存为图片形式,或自动隔0.1秒自动截笔记本全屏保存到指定文件夹

    Py:利用pyautogui实现自动将pdf文件(需手动设定pdf总页数)自动翻页并截取另存为图片形式,或自动隔0.1秒自动截笔记本全屏保存到指定文件夹 目录 实现步骤和结果 核心代码 实现步骤和结果 ...

  4. Entity Framework 6 Recipes 2nd Edition(13-6)译 - 自动编译的LINQ查询

    问题 你想为多次用到的查询提高性能,而且你不想添加额外的编码或配置. 解决方案 假设你有如Figure 13-8 所示的模型 Figure 13-8. A model with an Associat ...

  5. 嬴彻首款L3自动驾驶样车发布:自研全栈系统,满足高速全场景工况

    允中 发自 凹非寺  量子位 报道 | 公众号 QbitAI 3个月,推出L3自动驾驶卡车样车. 这是嬴彻科技刚刚披露的新速度. 2019年CES亚洲展上,嬴彻首次对外发布自主开发样车嬴彻1号. 而完 ...

  6. html自动汉字转拼音,输入汉字转换成拼音首字母js代码

    js代码 //根据文本框输入的汉字自动获取汉字拼音首字母到下拉列表中,支持多音字,需引入库pinying.js function query(){ var str = document.getElem ...

  7. Software knowledge Encyclopedia:extjs是一种软件,自动生成行号,支持checkbox全选

    extjs是一种软件.自动生成行号,支持checkbox全选,动态选择显示哪些列,支持本地以及远程分页,可以对单元格按照自己的想法进行渲染,这些也算可以想到的功能. 功能丰富,无人能出其右. 无论是界 ...

  8. 自动打开html网页脚本,开启网页全屏插件(自动开启网页全屏脚本js插件)

    开启网页全屏插件(自动开启网页全屏脚本js插件)是由作者陈鹏杰分享的一个浏览器扩展插件.通过本脚本,用户在网页加载完4秒后,启动网页全屏.非常简单方便快捷! 脚本描述: 在以下网页开启网页全屏 b 站 ...

  9. vue 视频播放插件vue-video-player自定义样式、自动播放设置、设置一开始全屏播放视频

    1.背景 项目中有涉及视频播放的需求,并且UI设计了样式,与原生的视频video组件有差异,所以使用了vue-video-player插件,并对vue-video-player进行样式改造,自定义播放 ...

  10. ajax的leiku,AJAX实现汉字和拼音搜索自动提示的效果(asp.net)

    实现该功能用到了两个页面,一个请求显示的页面(你可以使用的静态页面),一个用于获取关键字到数据表中模糊查询并获取满足条件的数据输出.这里的搜索提示实际上是用div来实现的,C#代码很简单,关键是看明白 ...

最新文章

  1. Web漏洞扫描(二:Windows server2008 R2操作系统(部署dvwa))
  2. R语言ggplot2可视化散点图、并以与y=0为界绘制基于散点包围的多边形(ploygon)、对于y=0坐标轴的上方和下方的多边形分别使用不同的颜色进行填充
  3. Github火爆的项目,用聪明的方式学习Vim!
  4. 软件测试中英文词汇汇总
  5. python下载图片、已知url_python 爬虫之requests爬取页面图片的url,并将图片下载到本地...
  6. 浅谈格雷码(Grey Code)在信息学竞赛中的应用
  7. php mysql修复_MySQL数据表损坏的巧妙修复
  8. C# 调用其他的动态库开发应注意的问题
  9. 随想录(git操作)
  10. 保存OpenCV中Mat_Vec3f格式的图像
  11. 4741G BIOS修复工具,黑刷bios有需要的收藏
  12. jxls中自定义函数的使用
  13. vue+elementUI中Dialog实现组件弹框以及子父组件页面传值
  14. 进击ReactNative-疾如风
  15. authorized_keys 不允许的操作
  16. 六西格玛dfss_六西格玛设计(DFSS)的方法和知识
  17. UNILUX频闪仪维修LITH-O-LIGHT-5频闪灯LOL-5/LOL-10
  18. 武汉大学计算机学院李明,第一届CSIG全国SLAM技术论坛成功举办
  19. zsh: command not found: conda
  20. U盘启动盘制作以及系统安装教程

热门文章

  1. maven安装及配置(详细版)
  2. 深度学习之MNIST数据集
  3. 数学模型:优化模型(一)存贮问题
  4. 在线英文翻译中文比较
  5. “泰迪杯”挑战赛 - 基于协同过滤的推荐算法研究与 GUI 设计
  6. 网络是怎样连接的_户根勤(带目录)
  7. 世界各国各行业投入产出表(2000-2014年)
  8. 5G终端难占用锚点小区导致无法驻留5G
  9. StringUtil 字符串处理工具
  10. wincc新手之路-安装与授权