遇到问题描述
- 使用
spring boot data包装high-level-client的NativeSearchQuery查询有以下问题:- 拼接比较复杂
- 不够直观
- 依赖es版本
track_total_hits只能是true或者false,不能指定一个具体的数,笔者的场景 如果为true查询数据量大,如果为false翻页时不能查询总页数。(需求设计时不是下划或者上划刷新)
- 使用
spring boot data包装high-level-client的searchTemplate- 虽然
mustache语法对初接触者有点难,但相对简洁 - 能够做到一些参数的详细控制如
track_total_hits
- 虽然
收获
-
- 怎样传数组, 将参数转换为 JSON,使用
{{#toJson}}parameter{{/toJson}}会将参数转换为 JSON。参考
GET _search/template { "source": "{ "query": { "terms": {{#toJson}}statuses{{/toJson}} }}", "params": { "statuses" : { "status": [ "pending", "published" ] } } }渲染出来的 DSL 就是:
{ "query": { "terms": { "status": [ "pending", "published" ] } } }- 传默认值 参考
- 怎样传数组, 将参数转换为 JSON,使用
实践
1. 模拟数据
InfoDocument
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.Document;
import java.util.Date;
@Data
@TypeAlias("infodev")
@Document(indexName = "infodev")
public class InfoDocument {
@Id
private long id;
private String stockCode;
private Date createDate;
private String industry;
private String title;
private String content;
}
Test
@Test
public void test_info() throws Exception {
for (int i = 0; i < 100; i++) {
InfoDocument infoDocument = new InfoDocument();
infoDocument.setId(i);
infoDocument.setStockCode("00000" + i);
infoDocument.setContent("content" + i);
infoDocument.setTitle("title" + i);
infoDocument.setCreateDate(new Date());
infoDocument.setIndustry("industry" + i);
elasticsearchOperations.save(infoDocument);
}
}
2. 使用Kibana提交查询模板
PUT _scripts/my-search-template3
{
"script": {
"lang": "mustache",
"source": """
{
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}",
"query": {
"bool": {
"must": [
{{#stockCode}}
{
"match": {
"stockCode": "{{stockCode}}"
}
}
{{/stockCode}}
{{#industry}}
,
{
"match": {
"industry": "{{industry}}"
}
}
{{/industry}}
{{#keywords}}
,{
"terms":{
"title":
{{#toJson}}keyword{{/toJson}}
}
},
{
"terms":{
"content":
{{#toJson}}keyword{{/toJson}}
}
}
{{/keywords}}
]
}
}
}
"""
}
}
3. 查看传入参数时查询模板的输出
POST _render/template
{
"id": "my-search-template3",
"params": {
"stockCode":"000002",
"keywords":{
"keyword":["title1","title2","content2","content3"]
}
}
}
输出
{
"template_output" : {
"from" : "0",
"size" : "10",
"query" : {
"bool" : {
"must" : [
{
"match" : {
"stockCode" : "000002"
}
},
{
"terms" : {
"title" : [
"title1",
"title2",
"content2",
"content3"
]
}
},
{
"terms" : {
"content" : [
"title1",
"title2",
"content2",
"content3"
]
}
}
]
}
}
}
}
使用查询模板查询
POST infodev/_search/template
{
"id": "my-search-template3",
"params": {
"stockCode":"000002",
"keywords":{
"keyword":["title1","title2","content2","content3"]
}
}
}
4. Java程序请求
@Test
public void testSearchTemplate() {
SearchTemplateRequest request = new SearchTemplateRequest();
request.setRequest(new SearchRequest("infodev"));
request.setScriptType(ScriptType.STORED);
request.setScript("my-search-template3");
Map<String, Object> map = new HashMap<>();
map.put("stockCode", "000002");
Map<String, Object> keyword = new HashMap<>();
List list = new ArrayList<>();
list.add("title1");
list.add("title2");
list.add("content2");
list.add("content3");
keyword.put("keyword", list);
map.put("keywords", keyword);
request.setScriptParams(map);
SearchTemplateResponse response = null;
try {
response = restHighLevelClient.searchTemplate(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
SearchResponse searchResponse = response.getResponse();
}
response的值: