• elasticsearch18-自动补全实战


    请添加图片描述
    个人名片:

    博主酒徒ᝰ.
    个人简介沉醉在酒中,借着一股酒劲,去拼搏一个未来。
    本篇励志三人行,必有我师焉。

    请添加图片描述
    本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

    【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 点击观看

    二、自动补全

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

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

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

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

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

    方法:
    索引库无法修改,需要删除重建。
    从之前定义的hotel的索引库进行修改。

    ①. 获取索引库:

    GET /hotel
    
    • 1

    在这里插入图片描述

    复制mappings和settings。

    ②. 删除索引库:

    DELETE /hotel
    
    • 1

    ③. 建立索引库

    粘贴mappings和settings,进行修改完善。

    PUT /hotel
    {
      "mappings" : {
          "properties" : {
            "address" : {
              "type" : "keyword",
              "index" : false
            },
            "all" : {
              "type" : "text",
              "analyzer" : "text_analyzer",
              "search_analyzer": "ik_smart"
            },
            "brand" : {
              "type" : "keyword",
              "copy_to" : [
                "all"
              ]
            },
            "business" : {
              "type" : "keyword",
              "copy_to" : [
                "all"
              ]
            },
            "city" : {
              "type" : "keyword"
            },
            "id" : {
              "type" : "keyword"
            },
            "location" : {
              "type" : "geo_point"
            },
            "name" : {
              "type" : "text",
              "analyzer": "text_analyzer", 
              "search_analyzer": "ik_smart", 
              "copy_to" : [
                "all"
              ]
            },
            "pic" : {
              "type" : "keyword",
              "index" : false
            },
            "price" : {
              "type" : "integer"
            },
            "score" : {
              "type" : "integer"
            },
            "starName" : {
              "type" : "keyword"
            },
            "suggestion": {
              "type": "completion",
              "analyzer": "completion_analyzer"
            }
          }
        },
        "settings" : {
          "analysis": {
            "analyzer": {
              "text_analyzer": {
                "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_tokenizer": false
              }
            }
          }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    1. 修改HotelDoc实体

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

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

    代码如下:

    package cn.itcast.hotel.pojo;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.Arrays;
    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<String> 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();
            this.suggestion = Arrays.asList(this.brand, this.city, this.business);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    1. 重新导入

    重新执行之前编写的导入数据功能,可以看到新的酒店数据中包含了suggestion:
    再次执行单元测试中的批量导入。

    在这里插入图片描述
    结果:
    发现如果是2个商圈的话,会有顿号。需要进行处理。
    在这里插入图片描述
    将顿号进行分割

    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<String> 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("、")) {
                String[] arr = this.business.split("、");
                this.suggestion = new ArrayList<>();
                this.suggestion.add(this.brand);
                this.suggestion.add(this.city);
                Collections.addAll(this.suggestion, arr);
            }else {
                this.suggestion = Arrays.asList(this.brand, this.city, this.business);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    结果:
    在这里插入图片描述

    1. 自动补全查询的JavaAPI

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

    GET /hotel/_search
    {
      "suggest": {
        "suggestions": {
          "text": "h",
          "completion": {
            "field": "suggestion",
            "skip_duplicates": true,
            "size": 10
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    java代码,对应上面的es语句。

    @Test
    void testSuggestionSearch() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        request.source().suggest(new SuggestBuilder().addSuggestion(
                "mySuggestion",
                SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
        ));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    
        Suggest suggest = response.getSuggest();
        CompletionSuggestion suggestion = suggest.getSuggestion("mySuggestion");
        List<CompletionSuggestion.Entry.Option> options = suggestion.getOptions();
        List<String> list = new ArrayList<>(options.size());
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            list.add(text);
        }
        System.out.println(list);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果:
    在这里插入图片描述

    1. 实现搜索框自动补全

    查看前端页面,可以发现当我们在输入框键入时,前端会发起ajax请求:
    在这里插入图片描述

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

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

    @GetMapping("/suggestion")
    public List<String> getSuggestions(@org.springframework.web.bind.annotation.RequestParam("key") String key) {
        return hotelService.getSuggestions(key);
    }
    
    • 1
    • 2
    • 3
    • 4

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

    List<String> getSuggestions(String key);
    
    • 1

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

    @Override
    public List<String> getSuggestions(String key) {
        try {
            SearchRequest request = new SearchRequest("hotel");
            request.source().suggest(new SuggestBuilder().addSuggestion(
                    "MySuggestion",
                    SuggestBuilders
                            .completionSuggestion("suggestion")
                            .prefix(key)
                            .skipDuplicates(true)
                            .size(10)
            ));
    
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            Suggest suggest = response.getSuggest();
            CompletionSuggestion suggestion = suggest.getSuggestion("MySuggestion");
            List<CompletionSuggestion.Entry.Option> options = suggestion.getOptions();
            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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

  • 相关阅读:
    iVX低代码平台系列详解 -- 概述篇(二)
    使用 Amazon Rekognition API 进行文本检测和 OCR
    【论文解读】A Simple Meta-path-free Framework for Heterogeneous Network Embedding
    Java --- Mybatis的动态sql标签
    vue:基础:生命周期
    研究生复试核心竞争力:编程(加分项)
    Loongson Laptop应用/系统崩溃进入initramfs界面
    数据结构——时间复杂度&空间复杂度
    【go微服务】Protocol Buffers V3中文语法指南
    健身也内卷?这届网友用 Python 掌握了做标准俯卧撑的秘诀
  • 原文地址:https://blog.csdn.net/m0_65144570/article/details/132948134