zoukankan      html  css  js  c++  java
  • 基于elasticSearch实现自动补全

    基于elasticSearch实现自动补全

    整体流程

    1. 添加索引,并单独写一个字节点用来实现自动补全,并设置类型为completion
    PUT search_index
     {
            "mappings": {
                "properties": {
                    "fileName": {
                        "type": "text",
                        "analyzer": "ik_max_word",
                        "fields": {
                            "suggest": {
                                "type": "completion",
                                "analyzer": "ik_max_word"
                            }
                        }
                    },
                    "path": {
                        "type": "keyword",
                        "index": false
                    }
                }
            }
        }
    
    
    1. 插入数据
    POST /search_index/_doc
    {
        "fileName":"四川成都市龙泉驿生态环境局龙泉驿区3D气溶胶雷达监控采购项目的中标公告"
    }
    POST /search_index/_doc
    {
        "fileName":"气溶胶雷达租赁服务报价清单"
    }
    POST /search_index/_doc
    {
        "fileName":"四川省遂宁市安居生态环境局臭氧在线监测预警系统采购项目竞争性磋商终止(废标)公告"
    }
    
    1. 实现搜索补全
    POST /search_index/_search
    {
      "suggest": {
        "my_suggest_document": {
          "prefix": "四",
          "completion": {
            "field": "fileName.suggest"
          }
        }
      }
    }
    

    JAVA基于RestHighLevelClient客户端的实现

    1. 构建配置客户端连接

      @Configuration
      @EnableElasticsearchRepositories
      public class ElasticsearchConfiguration extends AbstractElasticsearchConfiguration {
      
      
          @Override
          @Bean
          public RestHighLevelClient elasticsearchClient() {
      
              final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                      .connectedTo("192.168.15.207:9200")
      
                      //.withConnectTimeout(Duration.ofSeconds(5))
                      //.withSocketTimeout(Duration.ofSeconds(3))
                      //.useSsl()
                      //.withDefaultHeaders(defaultHeaders)
                      //.withBasicAuth(username, password)
                      // ... other options
                      .build();
              return RestClients.create(clientConfiguration).rest();
          }
      
      //    @Bean
      //    public ElasticsearchRestTemplate restTemplate() throws Exception {
      //        return new ElasticsearchRestTemplate(elasticsearchClient());
      //    }
      
      }
      
      
      
    2. 配置Java bean

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Document(indexName = "search_index", type = "_doc", shards = 5, replicas = 1)
      public class DocumentPo implements Serializable {
          private static final long serialVersionUID = 3433260756083989671L;
          @Id
          public String id;
          @Field(type = FieldType.Keyword)  
         // @Field(type = FieldType.Text, analyzer = "ik_max_word")
          public String fileName;   
          @Field(index = false, type = FieldType.Keyword)
          public String compassPath;
      
      }
      
      
    3. 添加数据

      public interface DocumentRepository extends ElasticsearchRepository<DocumentPo,Long> {
      }
      
      //添加
      @Autowired
      DocumentRepository documentRepository;
      
      documentRepository.save(documentPo);
      
    4. 实现搜索

       @Autowired
          private RestHighLevelClient restHighLevelClient;
      
      @RequestMapping(value = "/by_contact",method = RequestMethod.GET)
          public Object getSearchSuggest(HttpServletRequest request, @RequestParam(value = "keyWord")String keyWord)  {
              //指定在哪个字段搜索
              String suggestField = "fileName.suggest";
              SearchRequest searchRequest = new SearchRequest("search_index");
              searchRequest.types("_doc");
              SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
              BoolQueryBuilder qb = QueryBuilders.boolQuery();
              SuggestionBuilder termSuggestionBuilder =SuggestBuilders.completionSuggestion(suggestField).prefix(keyWord).skipDuplicates(true).size(10);
              SuggestBuilder suggestBuilder = new SuggestBuilder();
              suggestBuilder.addSuggestion("my_suggest_document", termSuggestionBuilder );
              searchSourceBuilder.suggest(suggestBuilder);
              searchRequest.source(searchSourceBuilder);
              SearchResponse response = null;
              try {
                  response = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
              } catch (Exception e) {
                  System.out.println(e.getMessage());
              }
              Suggest suggest = response.getSuggest();
              List<String> keywords = null;
              if (suggest != null) {
                  keywords = new ArrayList<>();
                  List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries =
                          suggest.getSuggestion("my_suggest_document").getEntries();
                  for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry: entries) {
                      for (Suggest.Suggestion.Entry.Option option: entry.getOptions()) {
                          String keyword = option.getText().string();
                          if (!StringUtils.isEmpty(keyword)) {
                              if (keywords.contains(keyword)) {
                                  continue;
                              }
                              keywords.add(keyword);
                              if (keywords.size() >= 9) {
                                  break;
                              }
                          }
                      }
                  }
              }
              return keywords;
          }
      
      

    多个条件的搜索

     public SearchResponse autosuggestSearch() throws IOException {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder qb = QueryBuilders.boolQuery();
    
            PrefixQueryBuilder namePQBuilder = QueryBuilders.prefixQuery("address", "usa");
            PrefixQueryBuilder addressPQBuilder = QueryBuilders.prefixQuery("address", "usa");
            qb.should(namePQBuilder);
            qb.should(addressPQBuilder); //Similarly add more fields prefix queries.
            sourceBuilder.query(qb);
    
            SearchRequest searchRequest = new SearchRequest("employee").source(sourceBuilder);
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            System.out.println("Search JSON query 
    " + searchRequest.source().toString()); //Generated ES search JSON.
            return searchResponse;
        }
    

    参考网址

    https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html

    https://stackoverflow.com/questions/60397369/elasticsearch-7-6-3-java-highlevel-rest-client-auto-suggest-across-multiple-fi

    https://stackoverflow.com/questions/54399859/completion-suggester-in-elasticsearch-6-5-4-with-java-rest-client-api?answertab=votes#tab-top

    https://stackoverflow.com/questions/48657904/how-to-write-rest-high-level-client-query-for-prefix-suggestion/50707641

    https://blog.csdn.net/jonkee/article/details/115421810

    作者:Ants_double

    出处:https://www.cnblogs.com/ants_double/

    本文版权归作者和博客园所有,欢迎转载。转载请在留言板处留言给我,且在文章标明原文链接,谢谢!

    如果您觉得本篇博文对您有所收获,觉得我还算用心,请点击右下角的 [大拇指],谢谢!

  • 相关阅读:
    python的多线程是否没有用了
    解决“mongoengine.fields.ImproperlyConfigured: PIL library was not found”报错
    Django JSON 时间
    伪装浏览器根据经纬度解析地理位置
    Excel——使用VLOOKUP函数关联跨工作薄数据
    Python发送邮件(支持中文)
    Excel实用技巧
    修改tomcat应用日志默认编码格式
    AWS多个EIP的解决方案
    解决荣耀7烦人的情景智能提醒
  • 原文地址:https://www.cnblogs.com/ants_double/p/15029658.html
Copyright © 2011-2022 走看看