一、search template简介
elasticsearch提供了search template功能,其会在实际执行查询之前,对search template进行预处理并将参数填充到template中。
elasticsearch主要提供了两个API来支持search template
_scripts/用于对search template的维护;
_search/template使用search template进行搜索;
二、测试数据准备
批量index三个文档
POST _bulk{ "index" : { "_index" : "search_template_test", "_type" : "_doc", "_id" : "1" } }
{ "name":"zhang san", "age":30, "man":true, "address":"Hebei LangFang"}
{ "index" : { "_index" : "search_template_test", "_type" : "_doc", "_id" : "2" } }
{ "name":"li si", "age":20, "man":true, "address":"BeiJing HaiDian"}
{ "index" : { "_index" : "search_template_test", "_type" : "_doc", "_id" : "3" } }
{ "name":"liu hui", "age":40, "man":false, "address":"NeiMengGu ChiFeng"}
查询查看三个索引的文档
GET search_template_test/_search
{"took":6,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":3,"max_score":1,"hits":[{"_index":"search_template_test","_type":"_doc","_id":"2","_score":1,"_source":{"name":"li si","age":20,"man":true,"address":"BeiJing HaiDian"}},{"_index":"search_template_test","_type":"_doc","_id":"1","_score":1,"_source":{"name":"zhang san","age":30,"man":true,"address":"Hebei LangFang"}},{"_index":"search_template_test","_type":"_doc","_id":"3","_score":1,"_source":{"name":"liu hui","age":40,"man":false,"address":"NeiMengGu ChiFeng"}}]}
}
三、维护search template
我们新建id为search_template_test.match_name的search template,其主要是查询match 字段name;
POST _scripts/search_template_test.match_name
{"script": { "lang": "mustache","source": {"query": {"match": {"name": "{{name_val}}"}}}}
}
查看我们创建的search template
GET _scripts/search_template_test.match_name{"_id":"search_template_test.match_name","found":true,"script":{"lang":"mustache","source":"{\"query\":{\"match\":{\"name\":\"{{name_val}}\"}}}","options":{"content_type":"application/json; charset=UTF-8"}}
}
删除我们创建的search template
DELET _scripts/search_template_test.match_name
{"acknowledged":true
}
elasticsearch提供了API支持我们查看预处理最终形成的查询语句;
POST _render/template/search_template_test.match_name
{"params":{"name_val":"zhang li"}
}{"template_output":{"query":{"match":{"name":"zhang li"}}}
}
四、使用search template
我们可以像下边这样使用search template
POST search_template_test/_search/template
{"id": "search_template_test.match_name", "params": {"name_val":"zhang li"}
}{"took":1,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":0.2876821,"hits":[{"_index":"search_template_test","_type":"_doc","_id":"2","_score":0.2876821,"_source":{"name":"li si","age":20,"man":true,"address":"BeiJing HaiDian"}},{"_index":"search_template_test","_type":"_doc","_id":"1","_score":0.2876821,"_source":{"name":"zhang san","age":30,"man":true,"address":"Hebei LangFang"}}]}
}
执行search template也支持使用explain来调试查看elasticsearch的打分情况;
POST search_template_test/_search/template
{"id": "search_template_test.match_name", "params": {"name_val":"zhang li"},"explain":true
}{"took":3,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":0.2876821,"hits":[{"_shard":"[search_template_test][2]","_node":"Sl6S4Kn2Rh-BdNgaM3ZwJg","_index":"search_template_test","_type":"_doc","_id":"2","_score":0.2876821,"_source":{"name":"li si","age":20,"man":true,"address":"BeiJing HaiDian"},"_explanation":{"value":0.2876821,"description":"sum of:","details":[{"value":0.2876821,"description":"weight(name:li in 0) [PerFieldSimilarity], result of:","details":[......]}]}},{"_shard":"[search_template_test][3]","_node":"Sl6S4Kn2Rh-BdNgaM3ZwJg","_index":"search_template_test","_type":"_doc","_id":"1","_score":0.2876821,"_source":{"name":"zhang san","age":30,"man":true,"address":"Hebei LangFang"},"_explanation":{"value":0.2876821,"description":"sum of:","details":[{"value":0.2876821,"description":"weight(name:zhang in 0) [PerFieldSimilarity], result of:","details":[......]}]}}]}
}
执行search template也支持使用profile来调试查看elasticsearch的查询执行情况;
POST search_template_test/_search/template
{"id": "search_template_test.match_name", "params": {"name_val":"zhang li"},"profile":true
}{"took":11,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":0.2876821,"hits":[]},"profile":{"shards":[{"id":"[Sl6S4Kn2Rh-BdNgaM3ZwJg][search_template_test][0]","searches":[{"query":[{"type":"BooleanQuery","description":"name:zhang name:li","time_in_nanos":308301,"breakdown":{"score":0,"build_scorer_count":0,"match_count":0,"create_weight":308300,"next_doc":0,"match":0,"create_weight_count":1,"next_doc_count":0,"score_count":0,"build_scorer":0,"advance":0,"advance_count":0},"children":[{"type":"TermQuery","description":"name:zhang","time_in_nanos":32901,"breakdown":{"score":0,"build_scorer_count":0,"match_count":0,"create_weight":32900,"next_doc":0,"match":0,"create_weight_count":1,"next_doc_count":0,"score_count":0,"build_scorer":0,"advance":0,"advance_count":0}},{"type":"TermQuery","description":"name:li","time_in_nanos":15901,"breakdown":{"score":0,"build_scorer_count":0,"match_count":0,"create_weight":15900,"next_doc":0,"match":0,"create_weight_count":1,"next_doc_count":0,"score_count":0,"build_scorer":0,"advance":0,"advance_count":0}}]}],"rewrite_time":42700,"collector":[{"name":"CancellableCollector","reason":"search_cancelled","time_in_nanos":700,"children":[{"name":"SimpleTopScoreDocCollector","reason":"search_top_hits","time_in_nanos":200}]}]}],"aggregations":[]}]}
}
五、使用search template处理复杂的查询
我们构建以下search template,其功能如下
可以通过name字段进行match,如果命中字段中的各个关键字相邻则有更高的权重打分,同时可以通过address字段进行模糊匹配,这三个查询只要命中一个即可;
man字段值必须符合输入的值;
POST _scripts/search_template_test.multi_search_template
{"script":{"lang":"mustache","source":{"query":{"bool":{"should":[{"match":{"name":"{{name}}"}},{"match_phrase_prefix":{"name":"{{name}}"}},{"query_string":{"default_field":"address","query":"{{#join delimiter=' '}}address{{/join delimiter=' '}}"}}],"filter":{"term":{"man":"{{man}}"}},"minimum_should_match":1}}}}
}
通过以下参数命中前两条数据
POST search_template_test/_search/template
{"id":"search_template_test.multi_search_template","params":{"name":"zhang sa","address":["*bei*","*chi*"],"man":true}
}{"took":10,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":1.8630463,"hits":[{"_index":"search_template_test","_type":"_doc","_id":"1","_score":1.8630463,"_source":{"name":"zhang san","age":30,"man":true,"address":"Hebei LangFang"}},{"_index":"search_template_test","_type":"_doc","_id":"2","_score":1,"_source":{"name":"li si","age":20,"man":true,"address":"BeiJing HaiDian"}}]}
}
我们将man字段设置为false,从而只匹配第三条记录;
POST search_template_test/_search/template
{"id":"search_template_test.multi_search_template","params":{"name":"zhang sa","address":["*bei*","*chi*"],"man":false}
}{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":1,"max_score":1,"hits":[{"_index":"search_template_test","_type":"_doc","_id":"3","_score":1,"_source":{"name":"liu hui","age":40,"man":false,"address":"NeiMengGu ChiFeng"}}]}
}