ElasticSearch High Level REST API(5)使用模板搜索

ElasticSearch Rest高级API 提供了多种搜索方式,除了前面讲到的search查询,ElasticSearch 还提供了通过模板搜索查询。

我们可以通过脚本预选注册模板,在注册模板时定义一个模板名称。在查询时通过模板名称调用该模板。

注册模板

@Autowired
private RestClient restClient;

@GetMapping("template/register")
public String registerTemplate() {
    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 scriptRequest = new Request("POST", "_scripts/title_search");
    scriptRequest.setJsonEntity(template);

    try {
        Response response = restClient.performRequest(scriptRequest);
        //restClient.close();
        return JSON.toJSONString(response);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "";
}
{
    "entity":{
        "chunked":false,
        "content":{

        },
        "contentLength":21,
        "contentType":{
            "buffer":{
                "empty":false,
                "full":false
            },
            "elements":[
                {
                    "name":"application/json",
                    "parameterCount":1,
                    "parameters":[
                        {
                            "name":"charset",
                            "value":"UTF-8"
                        }
                    ]
                }
            ],
            "name":"content-type",
            "value":"application/json; charset=UTF-8",
            "valuePos":13
        },
        "repeatable":false,
        "streaming":true
    },
    "headers":[
        {
            "$ref":"$.entity.contentType"
        },
        {
            "buffer":{
                "empty":false,
                "full":false
            },
            "elements":[
                {
                    "name":"21",
                    "parameterCount":0,
                    "parameters":[

                    ]
                }
            ],
            "name":"content-length",
            "value":"21",
            "valuePos":15
        }
    ],
    "host":{
        "hostName":"192.168.165.239",
        "port":9200,
        "schemeName":"http"
    },
    "requestLine":{
        "method":"POST",
        "protocolVersion":{
            "major":1,
            "minor":1,
            "protocol":"HTTP"
        },
        "uri":"_scripts/title_search"
    },
    "statusLine":{
        "protocolVersion":{
            "$ref":"$.requestLine.protocolVersion"
        },
        "reasonPhrase":"OK",
        "statusCode":200
    },
    "warnings":[

    ]
}

由于ElasticSearch 6.5-7.1版本的高级Rest API中暂时还没有提供用于注册模板的存储脚本,所以本示例中使用的低级REST客户端。本示例中注册了一个名为title_search的模板

有了这个模板就可以通过title_search去调用,动态的将查询参数添加到模板中去。模板调用示例如下:

@GetMapping("template/search")
public void templateSearch() {
    try {
        SearchTemplateRequest request = new SearchTemplateRequest();
        request.setRequest(new SearchRequest("test"));

        request.setScriptType(ScriptType.STORED);
        request.setScript("title_search");

        Map<String, Object> params = new HashMap<>();
        params.put("key", "name");
        params.put("value", "Joe.Ye");
        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) {
                log.info(hit.getSourceAsString());
            }
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
{"name":"Joe.Ye","email":"yezhou@yezhou.org","homepage":"http://www.appblog.cn"}
{"name":"Joe.Ye","age":28,"homepage":"http://www.appblog.cn"}
{"name":"Joe.Ye","email":"yezhou@yezhou.org","homepage":"http://www.appblog.cn"}
{"name":"Joe.Ye@AppBlog.CN","email":"yezhou@yezhou.org","age":18,"homepage":"http://www.appblog.cn"}
{"name":"Joe.Ye@AppBlog.CN","age":18,"homepage":"http://www.appblog.cn"}

针对每个模板我们执行一次搜索请求,如果我们工作中针对同一模板可能会有不止一次的请求,如果每个请求都去单独执行的话未免有点繁琐。我们可以通过multiTemplateSearch实现一次请求实现多条搜索,示例如下:

@GetMapping("template/multiSearch")
public void multiTemplateSearch() {
    String[] searchTerms = {"Joe.Ye", "Xiong"}; // 要搜索的条件
    MultiSearchTemplateRequest multiRequest = new MultiSearchTemplateRequest();
    for (String searchTerm : searchTerms) {
        SearchTemplateRequest request = new SearchTemplateRequest();
        request.setRequest(new SearchRequest("person")); //指定为person索引库

        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(); //搜索请求失败返回错误信息
                log.info(error);
            } else {
                SearchTemplateResponse searchTemplateResponse = item.getResponse();
                SearchResponse response = searchTemplateResponse.getResponse();
                SearchHits hits = response.getHits();
                for (SearchHit hit : hits) {
                    log.info(hit.getSourceAsString());
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
{"age":28,"height":175.2,"name":"Joe.Ye"}
{"age":26,"height":165.5,"name":"Xiong"}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/19/elasticsearch-high-level-rest-api-using-template-search/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
ElasticSearch High Level REST API(5)使用模板搜索
ElasticSearch Rest高级API 提供了多种搜索方式,除了前面讲到的search查询,ElasticSearch 还提供了通过模板搜索查询。 我们可以通过脚本预选注册模板,在注……
<<上一篇
下一篇>>
文章目录
关闭
目 录