作者:刘晓国
我们知道有的 Elasticsearch 的查询是非常耗时的。我们可以使用 _validate API 来对我们的 DSL 搜索进行一些验证。在很多的情况下,我们甚至可以使用这个 API 来验证不同的查询方法之间的区别或相同的地方。Elasticsearch 的 DSL 最终会转换为 Apache Lucene 的查询。今天,我将使用一个例子来展示这个 API 的用法。
首先,我们创建一个如下的索引及文档:
PUT my_index/_doc/1 { "content": "I like Elastic search because of its fast search speed, scalability and relevance" }
我们创建了上述的一个索引叫做 my_index,并且含有一个文档。
我们可以针对这个文档进行如下的查询:
GET my_index/_search { "query": { "match": { "content": { "query": "Elastic speed scalability relevance", "minimum_should_match": 2 } } } }
上面的查询返回的结果是:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.1507283, "hits" : [ { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_score" : 1.1507283, "_source" : { "content" : "I like Elastic search because of its fast search speed, scalability and relevance" } } ] } }
上面的查询显示了一个分数为 1.15,并且我们查询的结果是文档含有 Elastic speed scalability relevance 这其中四个关键字中的任何两个。
在 Elasticsearch 中,我们也可以使用另外一种方法来进行查询:
GET my_index/_search { "query": { "bool": { "should": [ { "match": { "content": "Elastic" } }, { "match": { "content": "speed" } }, { "match": { "content": "scalability" } }, { "match": { "content": "relevance" } } ], "minimum_should_match": 2 } } }
上面的查询返回的结果是:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.1507283, "hits" : [ { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_score" : 1.1507283, "_source" : { "content" : "I like Elastic search because of its fast search speed, scalability and relevance" } } ] } }
我们发现这两种方法查询的结果是完全一样的,而且它们的得分也是一样的。都是 1.15,那这两种方法到底是一样的吗?
我们可以通过 _validate API 接口来进行比较:
GET my_index/_validate/query?rewrite=true { "query": { "bool": { "should": [ { "match": { "content": "Elastic" } }, { "match": { "content": "speed" } }, { "match": { "content": "scalability" } }, { "match": { "content": "relevance" } } ], "minimum_should_match": 2 } } }
上面的命令的返回结果是:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true, "explanations" : [ { "index" : "my_index", "valid" : true, "explanation" : "(content:elastic content:speed content:scalability content:relevance)~2" } ] }
在 explanations 这个部分,我们可以看到
"explanation" : "(content:elastic content:speed content:scalability content:relevance)~2"
这个部分是真正要在 Apache Lucene 的部分进行查询的方法。
我们可以使用同样的方法来对 match 查询来进行验证:
GET my_index/_validate/query?rewrite=true { "query": { "match": { "content": { "query": "Elastic speed scalability relevance", "minimum_should_match": 2 } } } }
上面的方法返回的结果是:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true, "explanations" : [ { "index" : "my_index", "valid" : true, "explanation" : "(content:elastic content:speed content:scalability content:relevance)~2" } ] }
从上面的结果可以看出来,这两种方法的查询的结果是完全一样的。针对 Apache Lucene 的查询完全是一样的,虽然它们的 DSL 的写法完全不同。
我们甚至可以针对如下的查询来进行验证:
GET my_index/_validate/query?rewrite=true { "query": { "query_string": { "default_field": "content", "query": "Elastic speed scalability relevance", "minimum_should_match": "50%" } } }
上面的查询结果为:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true, "explanations" : [ { "index" : "my_index", "valid" : true, "explanation" : "(content:elastic content:speed content:scalability content:relevance)~2" } ] }
显然它的查询结果和之前的没有什么不一样的。
我们也可以利用 explain 参数来对查询进行解释,比如:
GET my_index/_validate/query?explain=true { "query": { "match": { "content": { "query": "Elastic speed scalability relevance", "minimum_should_match": 2 } } } }
上面显示的结果和之前的是一样的:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true, "explanations" : [ { "index" : "my_index", "valid" : true, "explanation" : "(content:elastic content:speed content:scalability content:relevance)~2" } ] }
如果我们不加任何的参数,我们并没有执行这个查询,只是验证一下查询是否为有效的查询:
GET my_index/_validate/query { "query": { "match": { "content": { "query": "Elastic speed scalability relevance", "minimum_should_match": 2 } } } }
上面返回的结果为:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true }
上面验证是成功的。