Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能

马肤
这是懒羊羊

文章目录

  • ⛄引言
  • 一、分词器
    • ⛅拼音分词器
    • ⚡自定义分词器
    • 二、自动补全查询
    • 三、自动补全
      • ⌚业务需求
      • ⏰实现酒店搜索自动补全
      • 四、效果图
      • ⛵小结

        ⛄引言

        本文参考黑马 分布式Elastic search

        Elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容

        像京东这样的提示应该如何实现?

        Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第1张

        可通过ES实现该自动补全功能,搭载分词器配合使用!

        本篇文章将讲解 Elastic Search 如何使用分词器实现自动补全功能,以及 在项目实战中如何通过完成自动补全的需求开发

        一、分词器

        为什么要使用分词器呢,因为我们要实现自动补全功能,要对输入的文字进行分词,从而更好的查询结果集

        ⛅拼音分词器

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

        Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第2张

        下载zip,安装方式如下:

        • 解压,通过工具上传至 elasticsearch的plugin目录
        • 重启elasticsearch
        • 进行测试拼音分词器

          重启命令: docker restart es

          测试方法:

          POST /_analyze
          {
            "text": "希尔顿酒店还不错",
            "analyzer": "pinyin"
          }
          

          Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第3张

          ⚡自定义分词器

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

          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"
                  }
                }
              }
            }
            

            测试

            Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第4张

            总结:

            如何使用拼音分词器?

            • 下载pinyin分词器

            • 解压并放到elasticsearch的plugin目录

            • 重启即可

              如何自定义分词器?

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

              • character filter

              • tokenizer

              • filter

                拼音分词器注意事项?

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

                  二、自动补全查询

                  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": "sw" // 关键字
                            "completion": {
                              "field": "title", // 补全查询的字段
                              "skip_duplicates": true, // 跳过重复的
                              "size": 10 // 获取前10条结果
                            }
                          }
                        }
                      }
                      

                      Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第5张

                      测试出一条数据

                      三、自动补全

                      ⌚业务需求

                      在页面实现 输入 文字或者拼音,自动提示匹配的列表数据

                      Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第6张

                      根据酒店数据和地址进行查询数据列表

                      ⏰实现酒店搜索自动补全

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

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

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

                      1. 修改hotel索引库结构,设置自定义拼音分词器
                      2. 修改索引库的name、all字段,使用自定义分词器
                      3. 索引库添加一个新字段suggestion,类型为completion类型,使用自定义的分词器
                      4. 给HotelDoc类添加suggestion字段,内容包含brand、business
                      5. 重新导入数据到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"
                            }
                          }
                        }
                      }
                      

                      修改HotelDoc实体

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

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

                      代码如下:

                      @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();
                              //拼装数据,把数据一个个放到数组中
                              if (this.business.contains("/") || this.business.contains("、") || this.business.contains(",")) {
                                  String[] arr = {};
                                  if (this.business.contains("/")) {
                                      arr = this.business.split("/");
                                  } else if (this.business.contains("、")) {
                                      arr = this.business.split("、");
                                  } else if (this.business.contains(",")) {
                                      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);
                              }
                          }
                      }
                      

                      执行方法重新导入酒店数据

                      @Test
                          void testBulkRequest() throws IOException {
                              // 查询所有的酒店数据
                              List list = hotelService.list();
                              // 1.准备Request
                              BulkRequest request = new BulkRequest();
                              // 2.准备参数
                              for (Hotel hotel : list) {
                                  // 2.1.转为HotelDoc
                                  HotelDoc hotelDoc = new HotelDoc(hotel);
                                  // 2.2.转json
                                  String json = JSON.toJSONString(hotelDoc);
                                  // 2.3.添加请求
                                  request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));
                              }
                              // 3.发送请求
                              client.bulk(request, RequestOptions.DEFAULT);
                          }
                      

                      自动补全查询API

                      自动补全查询DSL 对应代码

                      Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第7张

                      自动补全结果解析 对应代码DSL

                      Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第8张

                      核心源码

                      在Controller类新增接口

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

                      Service业务代码

                      public List getSuggestions(String prefix) {
                              //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)));
                              try {
                                  //3. 发送请求
                                  SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
                                  //4. 解析结果
                                  Suggest suggest = response.getSuggest();
                                  //根据补全查询名称获取补全结果
                                  CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
                                  //获取options
                                  List options = suggestions.getOptions();
                                  //遍历
                                  List result = new ArrayList(options.size());
                                  for (CompletionSuggestion.Entry.Option option : options) {
                                      result.add(option.getText().toString());
                                  }
                                  return result;
                              } catch (Exception e) {	
                                  e.printStackTrace();
                              }
                              return null;
                          }
                      

                      四、效果图

                      Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,没有,安装,li,第9张

                      ⛵小结

                      以上就是【Bug 终结者】对 Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能 的简单介绍,ES搜索引擎无疑是最优秀的分布式搜索引擎,使用它,可大大提高项目的灵活、高效性! 技术改变世界!!!

                      如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!


文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码