elasticsearch18-自动补全实战

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

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

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

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

目录

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

二、自动补全

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

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

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

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

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

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

①. 获取索引库:

GET /hotel

elasticsearch18-自动补全实战_第1张图片

复制mappings和settings。

②. 删除索引库:

DELETE /hotel

③. 建立索引库

粘贴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. 修改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. 重新导入

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

elasticsearch18-自动补全实战_第2张图片
结果:
发现如果是2个商圈的话,会有顿号。需要进行处理。
elasticsearch18-自动补全实战_第3张图片
将顿号进行分割

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);
        }
    }
}

结果:
elasticsearch18-自动补全实战_第4张图片

  1. 自动补全查询的JavaAPI

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

GET /hotel/_search
{
  "suggest": {
    "suggestions": {
      "text": "h",
      "completion": {
        "field": "suggestion",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

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. 实现搜索框自动补全

查看前端页面,可以发现当我们在输入框键入时,前端会发起ajax请求:
elasticsearch18-自动补全实战_第5张图片

返回值是补全词条的集合,类型为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);
}

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

List<String> getSuggestions(String key);

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);
    }
}

elasticsearch18-自动补全实战_第6张图片

你可能感兴趣的:(#,elasticsearch,wpf,elasticsearch,搜索引擎)