一、需要解决的问题
有的时候我们需要同时执行多个查询,并且需要得到每个单独查询的搜索结果,elasticsearch提供了multi search此需求的支持;
二、elasticsearch multi search简介
elasticsearch提供了multi search api来支持一个请求执行多个查询;
multi search api的请求体使用换行分割的JSON格式;
headern bodyn headern bodyn
multi search返回的结果是responses数组,每个查询对应一个数组元素;每个数组元素都有一个status字段指示查询是否执行成功,如果执行失败则error字段返回错误信息;
每个查询可以通过自己的header设置查询执行的index,也可以是空的JSON对象,这是在URL中指定的index执行查询;
三、数据准备
index以下四个文档
PUT /multi_test/_doc/1 { "name":"Google Chrome" } PUT /multi_test/_doc/2 { "name":"NotePad" } PUT /multi_test/_doc/3 { "name":"Word" } PUT /multi_test/_doc/4 { "name":"PyCharm" }
查询查看已经索引的数据
GET /multi_test/_search { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":4, "max_score":1, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"2", "_score":1, "_source":{ "name":"NotePad" } }, { "_index":"multi_test", "_type":"_doc", "_id":"4", "_score":1, "_source":{ "name":"PyCharm" } }, { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":1, "_source":{ "name":"Google Chrome" } }, { "_index":"multi_test", "_type":"_doc", "_id":"3", "_score":1, "_source":{ "name":"Word" } } ] } }
四、查询测试
我们构造以下四个查询同时执行
POST /multi_test/_msearch {} {"query":{"match":{"name":"google"}}} {} {"query":{"match":{"name":"nohit"}}} {} {"query":{"match":{"name":"word"}}} {} {"query":{"bool":{"should":[{"match":{"name":"word"}}, {"match":{"name":"pycharm"}}]}}}
我们可以看到不管查询是否命中结果,都会有一个responses数组元素对应;同时responses数组元素的顺序与查询是一 一对应的;
{ "responses":[ { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":0.2876821, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":0.2876821, "_source":{ "name":"Google Chrome" } } ] }, "status":200 }, { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":0, "max_score":null, "hits":[ ] }, "status":200 }, { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":0.2876821, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"3", "_score":0.2876821, "_source":{ "name":"Word" } } ] }, "status":200 }, { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":2, "max_score":0.6931472, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"4", "_score":0.6931472, "_source":{ "name":"PyCharm" } }, { "_index":"multi_test", "_type":"_doc", "_id":"3", "_score":0.2876821, "_source":{ "name":"Word" } } ] }, "status":200 } ] }
五、multi search对search template的支持
multi search api也支持search template;
muti search内联search template查询
POST /multi_test/_msearch/template {} { "source" : "{ "query": { "match": { "name" : "{{name}}" } } } }", "params": { "name": "google" } } {} { "source" : "{ "query": { "match_{{template}}": {} } }", "params": { "template": "all" } }
查询结果为
{ "responses":[ { "took":0, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":0.2876821, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":0.2876821, "_source":{ "name":"Google Chrome" } } ] } }, { "took":8, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":4, "max_score":1, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"2", "_score":1, "_source":{ "name":"NotePad" } }, { "_index":"multi_test", "_type":"_doc", "_id":"4", "_score":1, "_source":{ "name":"PyCharm" } }, { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":1, "_source":{ "name":"Google Chrome" } }, { "_index":"multi_test", "_type":"_doc", "_id":"3", "_score":1, "_source":{ "name":"Word" } } ] } } ] }
也可以直接新建search template
POST /_scripts/multi_test_name_template/ { "script":{ "lang":"mustache", "source":{ "query":{ "bool":{ "should":[ { "match":{ "name":"{{name}}" } }, { "wildcard":{ "name":"*{{name}}*" } } ] } } } } }
使用新建的search template进行搜索
POST /multi_test/_msearch/template {} { "id": "multi_test_name_template", "params": { "name": "oo" } } {} { "id": "multi_test_name_template", "params": { "name": "notepad" } }
搜索结果如下
{ "responses":[ { "took":1, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":1, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":1, "_source":{ "name":"Google Chrome" } } ] } }, { "took":1, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":1.6931472, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"2", "_score":1.6931472, "_source":{ "name":"NotePad" } } ] } } ] }
在search template中使用嵌套字段作为参数
POST /multi_test/_msearch/template {} { "source" : "{ "query": { "match": { "name" : "{{person.name}}" } } } }", "params": { "person":{"name": "google"} } }
搜索结果如下
{ "responses":[ { "took":3, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":0.2876821, "hits":[ { "_index":"multi_test", "_type":"_doc", "_id":"1", "_score":0.2876821, "_source":{ "name":"Google Chrome" } } ] } } ] }