多字段、多词、匹配不带query_string [英] Multi-field, multi-word, match without query_string
问题描述
我希望能够将多词搜索与多个字段进行匹配,其中搜索到的每个词都包含在任何字段中,任意组合.问题是我想避免使用 query_string.
I would like to be able to match a multi word search against multiple fields where every word searched is contained in any of the fields, any combination. The catch is I would like to avoid using query_string.
curl -X POST "http://localhost:9200/index/document/1" -d '{"id":1,"firstname":"john","middlename":"clark","lastname":"smith"}'
curl -X POST "http://localhost:9200/index/document/2" -d '{"id":2,"firstname":"john","middlename":"paladini","lastname":"miranda"}'
我希望搜索John Smith"只匹配文档 1.以下查询满足我的需要,但我宁愿避免使用 query_string,以防用户通过OR"、AND"和任何其他高级参数.
I would like the search for 'John Smith' to match only document 1. The following query does what I need but I would rather avoid using query_string in case the user passes "OR", "AND" and any of the other advanced params.
curl -X GET 'http://localhost:9200/index/_search?per_page=10&pretty' -d '{
"query": {
"query_string": {
"query": "john smith",
"default_operator": "AND",
"fields": [
"firstname",
"lastname",
"middlename"
]
}
}
}'
推荐答案
您正在寻找的是 多匹配查询,但它的执行方式与您希望的不同.
What you are looking for is the multi-match query, but it doesn't perform in quite the way you would like.
比较 validate 的输出multi_match
vs query_string
.
Compare the output of validate for multi_match
vs query_string
.
multi_match
(使用运算符 and
)将确保所有术语都存在于至少一个字段中:
multi_match
(with operator and
) will make sure that ALL terms exist in at least one field:
curl -XGET 'http://127.0.0.1:9200/_validate/query?pretty=1&explain=true' -d '
{
"multi_match" : {
"operator" : "and",
"fields" : [
"firstname",
"lastname"
],
"query" : "john smith"
}
}
'
# {
# "_shards" : {
# "failed" : 0,
# "successful" : 1,
# "total" : 1
# },
# "explanations" : [
# {
# "index" : "test",
# "explanation" : "((+lastname:john +lastname:smith) | (+firstname:john +firstname:smith))",
# "valid" : true
# }
# ],
# "valid" : true
# }
虽然 query_string
(使用 default_operator AND
)将检查每个术语是否存在于至少一个字段中:
While query_string
(with default_operator AND
) will check that EACH term exists in at least one field:
curl -XGET 'http://127.0.0.1:9200/_validate/query?pretty=1&explain=true' -d '
{
"query_string" : {
"fields" : [
"firstname",
"lastname"
],
"query" : "john smith",
"default_operator" : "AND"
}
}
'
# {
# "_shards" : {
# "failed" : 0,
# "successful" : 1,
# "total" : 1
# },
# "explanations" : [
# {
# "index" : "test",
# "explanation" : "+(firstname:john | lastname:john) +(firstname:smith | lastname:smith)",
# "valid" : true
# }
# ],
# "valid" : true
# }
所以你有几个选择来实现你的目标:
So you have a few choices to achieve what you are after:
在使用
query_string
预解析搜索词以提取每个单词,然后为每个单词生成一个multi_match
查询
Preparse the search terms to extract each word, then generate a multi_match
query per word
在名称字段的映射中使用 index_name
将它们的数据索引到单个字段中,然后您可以将其用于搜索.(就像您自己的自定义 all
字段):
Use index_name
in your mapping for the name fields to index their data into a single field, which you can then use for search. (like your own custom all
field):
如下:
curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1' -d '
{
"mappings" : {
"test" : {
"properties" : {
"firstname" : {
"index_name" : "name",
"type" : "string"
},
"lastname" : {
"index_name" : "name",
"type" : "string"
}
}
}
}
}
'
curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1' -d '
{
"firstname" : "john",
"lastname" : "smith"
}
'
curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d '
{
"query" : {
"match" : {
"name" : {
"operator" : "and",
"query" : "john smith"
}
}
}
}
'
# {
# "hits" : {
# "hits" : [
# {
# "_source" : {
# "firstname" : "john",
# "lastname" : "smith"
# },
# "_score" : 0.2712221,
# "_index" : "test",
# "_id" : "VJFU_RWbRNaeHF9wNM8fRA",
# "_type" : "test"
# }
# ],
# "max_score" : 0.2712221,
# "total" : 1
# },
# "timed_out" : false,
# "_shards" : {
# "failed" : 0,
# "successful" : 5,
# "total" : 5
# },
# "took" : 33
# }
但是请注意,firstname
和 lastname
不再可以独立搜索.两个字段的数据都已索引到name
.
Note however, that firstname
and lastname
are no longer searchable independently. The data for both fields has been indexed into name
.
您可以将多字段与path
参数使它们既可独立搜索又可一起搜索,如下所示:
You could use multi-fields with the path
parameter to make them searchable both independently and together, as follows:
curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1' -d '
{
"mappings" : {
"test" : {
"properties" : {
"firstname" : {
"fields" : {
"firstname" : {
"type" : "string"
},
"any_name" : {
"type" : "string"
}
},
"path" : "just_name",
"type" : "multi_field"
},
"lastname" : {
"fields" : {
"any_name" : {
"type" : "string"
},
"lastname" : {
"type" : "string"
}
},
"path" : "just_name",
"type" : "multi_field"
}
}
}
}
}
'
curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1' -d '
{
"firstname" : "john",
"lastname" : "smith"
}
'
搜索 any_name
字段有效:
curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d '
{
"query" : {
"match" : {
"any_name" : {
"operator" : "and",
"query" : "john smith"
}
}
}
}
'
# {
# "hits" : {
# "hits" : [
# {
# "_source" : {
# "firstname" : "john",
# "lastname" : "smith"
# },
# "_score" : 0.2712221,
# "_index" : "test",
# "_id" : "Xf9qqKt0TpCuyLWioNh-iQ",
# "_type" : "test"
# }
# ],
# "max_score" : 0.2712221,
# "total" : 1
# },
# "timed_out" : false,
# "_shards" : {
# "failed" : 0,
# "successful" : 5,
# "total" : 5
# },
# "took" : 11
# }
为 john AND smith
搜索 firstname
不起作用:
Searching firstname
for john AND smith
doesn't work:
curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d '
{
"query" : {
"match" : {
"firstname" : {
"operator" : "and",
"query" : "john smith"
}
}
}
}
'
# {
# "hits" : {
# "hits" : [],
# "max_score" : null,
# "total" : 0
# },
# "timed_out" : false,
# "_shards" : {
# "failed" : 0,
# "successful" : 5,
# "total" : 5
# },
# "took" : 2
# }
但是只为 john
搜索 firstname
工作正常:
But searching firstname
for just john
works correctly:
curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d '
{
"query" : {
"match" : {
"firstname" : {
"operator" : "and",
"query" : "john"
}
}
}
}
'
# {
# "hits" : {
# "hits" : [
# {
# "_source" : {
# "firstname" : "john",
# "lastname" : "smith"
# },
# "_score" : 0.30685282,
# "_index" : "test",
# "_id" : "Xf9qqKt0TpCuyLWioNh-iQ",
# "_type" : "test"
# }
# ],
# "max_score" : 0.30685282,
# "total" : 1
# },
# "timed_out" : false,
# "_shards" : {
# "failed" : 0,
# "successful" : 5,
# "total" : 5
# },
# "took" : 3
# }
这篇关于多字段、多词、匹配不带query_string的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!