ElasticSearch High Level REST API【5】使用模板搜索
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(); } }
执行结果如下