当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项
要实现根据字母做补全,就必须对文档按照拼音分词,GitHub上有拼音分词插件

解压到一个文件夹中去
上传到服务器中,elasticsearch的plugin目录

重启elasticsearch
docker restart es
- POST /_analyze
- {
- "text": "如家酒店还不错",
- "analyzer": "pinyin"
- }
返回拼音

默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。
elasticsearch中分词器(analyzer)的组成包含三部分:
character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

- PUT /myanalyzer
- {
- "settings": {
- "analysis": {
- "analyzer": {
- "my_analyzer": {
- "tokenizer": "ik_max_word",
- "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": {
- "name": {
- "type": "text",
- "analyzer": "my_analyzer",
- "search_analyzer": "ik_smart"
- }
- }
- }
- }
- POST /myanalyzer/_analyze
- {
- "text": ["华美达酒店还不错"],
- "analyzer": "my_analyzer"
- }
结果

- 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"
- }
- }
- }
- }
- 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);
- }
- }
- }
- @Test
- void testBulkRequest() throws IOException {
- // 批量查询酒店数据
- List
hotels = hotelService.list(); -
- // 1.创建Request
- BulkRequest request = new BulkRequest();
- // 2.准备参数,添加多个新增的Request
- for (Hotel hotel : hotels) {
- // 2.1.转换为文档类型HotelDoc
- HotelDoc hotelDoc = new HotelDoc(hotel);
- // 2.2.创建新增文档的Request对象
- request.add(new IndexRequest("hotel")
- .id(hotelDoc.getId().toString())
- .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
- }
- // 3.发送请求
- client.bulk(request, RequestOptions.DEFAULT);
- }
-
-
- import cn.itcast.hotel.pojo.PageResult;
- import cn.itcast.hotel.pojo.RequestParams;
- import cn.itcast.hotel.service.IHotelService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
- import java.util.List;
- import java.util.Map;
-
- @RestController
- @RequestMapping("/hotel")
- public class HotelController {
-
- @Autowired
- private IHotelService hotelService;
- // 搜索酒店数据
-
-
- @GetMapping("suggestion")
- public List
getSuggestions(@RequestParam("key") String prefix) { - return hotelService.getSuggestions(prefix);
- }
- }
-
- import cn.itcast.hotel.mapper.HotelMapper;
- import cn.itcast.hotel.pojo.Hotel;
- import cn.itcast.hotel.pojo.HotelDoc;
- import cn.itcast.hotel.pojo.PageResult;
- import cn.itcast.hotel.pojo.RequestParams;
- import cn.itcast.hotel.service.IHotelService;
- import com.alibaba.fastjson.JSON;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import org.elasticsearch.action.search.SearchRequest;
- import org.elasticsearch.action.search.SearchResponse;
-
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.geo.GeoPoint;
- import org.elasticsearch.common.unit.DistanceUnit;
- import org.elasticsearch.index.query.BoolQueryBuilder;
- import org.elasticsearch.index.query.QueryBuilders;
- import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
- import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
- import org.elasticsearch.search.SearchHit;
- import org.elasticsearch.search.SearchHits;
- import org.elasticsearch.search.aggregations.AggregationBuilders;
- import org.elasticsearch.search.aggregations.Aggregations;
- import org.elasticsearch.search.aggregations.bucket.terms.Terms;
- import org.elasticsearch.search.sort.SortBuilders;
- import org.elasticsearch.search.sort.SortOrder;
- import org.elasticsearch.search.suggest.Suggest;
- import org.elasticsearch.search.suggest.SuggestBuilder;
- import org.elasticsearch.search.suggest.SuggestBuilders;
- import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- @Service
- public class HotelService extends ServiceImpl
implements IHotelService { -
- @Autowired
- private RestHighLevelClient client;
-
-
-
- @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);
- }
- }
-
-
-
-
-
-
- }
