Elasticsearch 您所在的位置:网站首页 拼音搜索引擎是什么 Elasticsearch

Elasticsearch

2024-06-18 21:28| 来源: 网络整理| 查看: 265

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

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

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

2.1.拼音分词器

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

资料中也提供了拼音分词器的安装包:

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

​ ①解压

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

​ ③重启elasticsearch

​ ④测试

详细安装步骤可以参考IK分词器的安装过程。

测试用法如下:

POST /_analyze {   "text": "如家酒店还不错",   "analyzer": "pinyin" }

结果:

2.2.自定义分词器

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

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

character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smarttokenizer 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" // 搜索时使用,避免同音字       }     }   } }

测试:

总结:

如何使用拼音分词器?

①下载pinyin分词器②解压并放到elasticsearch的plugin目录③重启即可

如何自定义分词器?

①创建索引库时,在settings中配置,可以包含三部分②character filter③tokenizer④filter

拼音分词器注意事项?

为了避免搜索到同音字,搜索时不要使用拼音分词器 2.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条结果       }     }   } } 2.4.实现酒店搜索框自动补全

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

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

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

修改hotel索引库结构,设置自定义拼音分词器修改索引库的name、all字段,使用自定义分词器索引库添加一个新字段suggestion,类型为completion类型,使用自定义的分词器给HotelDoc类添加suggestion字段,内容包含brand、business重新导入数据到hotel库 2.4.1.修改酒店映射结构

代码如下:

// 酒店数据索引库 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" } } } } 2.4.2.修改HotelDoc实体

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

因此我们在HotelDoc中添加一个suggestion字段,类型为List,然后将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 Long id; private String name; private String address; private Integer price; private Integer score; private String brand; private String city; private String starName; private String business; private String location; private String pic; private Object distance; private Boolean isAD; private List suggestion; public HotelDoc(Hotel hotel) { this.id = hotel.getId(); this.name = hotel.getName(); this.address = hotel.getAddress(); this.price = hotel.getPrice(); this.score = hotel.getScore(); this.brand = hotel.getBrand(); this.city = hotel.getCity(); this.starName = hotel.getStarName(); this.business = hotel.getBusiness(); this.location = hotel.getLatitude() + ", " + hotel.getLongitude(); this.pic = hotel.getPic(); // 组装suggestion if(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); } } } 2.4.3.重新导入

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

2.4.4.自动补全查询的JavaAPI

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

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

2.4.5.实现搜索框自动补全

查看前端页面,可以发现当我们在输入框键入时,前端会发起ajax请求:

返回值是补全词条的集合,类型为List

1)在cn.itcast.hotel.web包下的HotelController中添加新接口,接收新的请求:

@GetMapping("suggestion") public List getSuggestions(@RequestParam("key") String prefix) { return hotelService.getSuggestions(prefix); }

2)在cn.itcast.hotel.service包下的IhotelService中添加方法:

List getSuggestions(String prefix);

3)在cn.itcast.hotel.service.impl.HotelService中实现该方法:

@Override public List getSuggestions(String prefix) { try { // 1.准备Request SearchRequest request = new SearchRequest("hotel"); // 2.准备DSL request.source().suggest(new SuggestBuilder().addSuggestion( "suggestions", SuggestBuilders.completionSuggestion("suggestion") .prefix(prefix) .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.获取options List options = suggestions.getOptions(); // 4.3.遍历 List 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); } }

资料地址: 链接:https://pan.baidu.com/s/1cQVyPGjyk-_t3b04wkcMfg 提取码:1211



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有