ElasticSearch Rest高級API 提供了多種搜索方式,除了前面講到的search查詢,ElasticSearch 還提供了通過模板搜索查詢。我個人比較喜歡這種方式。
我們可以通過腳本預選注冊模板,在注冊模板時定義一個模板名稱。在查詢時通過模板名稱調用該模板。首先演示下如何注冊模板:
public void registTemplate(){ RestClient restClient = elasticClient.getRestClient(); String template = "{\n" + " \"script\":{\n" + " \"lang\":\"mustache\",\n" + " \"source\":{\n" + " \"query\":{\n" + " \"match\":{\n" + " \"{{key}}\":\"{{value}}\"\n" + " }\n" + " },\n" + " \"size\":\"{{size}}\"\n" + " }\n" + " }\n" + "}"; Request scriptRequest1 = new Request("POST", "_scripts/title_search"); scriptRequest1.setJsonEntity(template); try { restClient.performRequest(scriptRequest1); restClient.close(); } catch (IOException e) { e.printStackTrace(); } }
由於ElasticSearch 6.5版本的高級Rest API中暫時還沒有提供用於注冊模板的存儲腳本,所以本示例中使用的低級REST客戶端。本示例中注冊了一個名為“title_search”的模板
有了這個模板就可以通過“title_search”去調用,動態的將查詢參數添加到模板中去。模板調用示例如下:
public void templateSearch(){ RestHighLevelClient client = elasticClient.getRestHighLevelClient(); try { SearchTemplateRequest request = new SearchTemplateRequest(); request.setRequest(new SearchRequest("posts")); request.setScriptType(ScriptType.STORED); request.setScript("title_search"); Map<String, Object> params = new HashMap<>(); params.put("key", "name"); params.put("value", "福賣福"); params.put("size", 5); request.setScriptParams(params); try { SearchTemplateResponse searchTemplateResponse = client.searchTemplate(request, RequestOptions.DEFAULT); SearchHit[] hits = searchTemplateResponse.getResponse().getHits().getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); } client.close(); } catch (IOException e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } }
針對每個模板我們執行一次搜索請求,如果我們工作中針對同一模板可能會有不止一次的請求,如果每個請求都去單獨執行的話未免有點繁瑣。我們可以通過msearchTemplate
來實現一次請求實現多條搜索,示例如下:
public void multiTemplateSearch(){ RestHighLevelClient client = elasticClient.getRestHighLevelClient(); String [] searchTerms = {"周大福", "特博士", "詹姆斯"}; // 要搜索的條件 MultiSearchTemplateRequest multiRequest = new MultiSearchTemplateRequest(); for (String searchTerm : searchTerms) { SearchTemplateRequest request = new SearchTemplateRequest(); request.setRequest(new SearchRequest("posts")); //指定為posts索引庫 request.setScriptType(ScriptType.INLINE); request.setScript( "{\n" + " \"query\":{\n" + " \"match\":{\n" + " \"{{key}}\":\"{{value}}\"\n" + " }\n" + " },\n" + " \"size\":\"{{size}}\"\n" + "}"); Map<String, Object> scriptParams = new HashMap<>(); //向模板中填充對應值 scriptParams.put("key", "name"); scriptParams.put("value", searchTerm); scriptParams.put("size", 5); request.setScriptParams(scriptParams); multiRequest.add(request); } //執行查詢 try { MultiSearchTemplateResponse multiResponse = client.msearchTemplate(multiRequest, RequestOptions.DEFAULT); //返回一組響應 ,每個請求對應一個響應 for (MultiSearchTemplateResponse.Item item : multiResponse.getResponses()) { if (item.isFailure()) { String error = item.getFailureMessage(); //搜索請求失敗返回錯誤信息 }else { SearchTemplateResponse searchTemplateResponse = item.getResponse(); SearchResponse response = searchTemplateResponse.getResponse(); SearchHits hits = response.getHits(); System.out.println("----------"); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); } } } } catch (IOException e) { e.printStackTrace(); } }
執行結果如下