基於elasticSearch實現自動補全
阿新 • • 發佈:2021-07-19
基於elasticSearch實現自動補全
-
為什麼要用es來實現?
因為能共用一個搜尋服務,並且穩定,能利用已有的分詞器。
-
有多少種實現方法?本文用的是哪一種?
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html
本文用的
completion
suggester 來實現的。 -
已經有那麼多文章了,為何還要寫?
- 很多文章沒有及時更新
- 記錄自己的理解
整體流程
- 新增索引,並單獨寫一個位元組點用來實現自動補全,並設定型別為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 } } } }
- 插入資料
POST /search_index/_doc
{
"fileName":"四川成都市龍泉驛生態環境局龍泉驛區3D氣溶膠雷達監控採購專案的中標公告"
}
POST /search_index/_doc
{
"fileName":"氣溶膠雷達租賃服務報價清單"
}
POST /search_index/_doc
{
"fileName":"四川省遂寧市安居生態環境局臭氧線上監測預警系統採購專案競爭性磋商終止(廢標)公告"
}
- 實現搜尋補全
POST /search_index/_search { "suggest": { "my_suggest_document": { "prefix": "四", "completion": { "field": "fileName.suggest" } } } }
JAVA基於RestHighLevelClient客戶端的實現
-
構建配置客戶端連線
@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()); // } }
-
配置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; }
-
新增資料
public interface DocumentRepository extends ElasticsearchRepository<DocumentPo,Long> { } //新增 @Autowired DocumentRepository documentRepository; documentRepository.save(documentPo);
-
實現搜尋
@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 \n" + searchRequest.source().toString()); //Generated ES search JSON.
return searchResponse;
}
參考網址
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html
https://blog.csdn.net/jonkee/article/details/115421810
作者:Ants_double
出處:https://www.cnblogs.com/ants_double/
本文版權歸作者和部落格園所有,歡迎轉載。轉載請在留言板處留言給我,且在文章標明原文連結,謝謝!
如果您覺得本篇博文對您有所收穫,覺得我還算用心,請點選右下角的 [大拇指],謝謝!