多字段,多字,匹配没有query_string
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多字段,多字,匹配没有query_string相关的知识,希望对你有一定的参考价值。
我希望能够将多字搜索与多个字段匹配,其中搜索的每个字都包含在任何字段中,任何组合中。我想避免使用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”和任何其他高级参数。
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"
]
}
}
}'
你正在寻找的是multi-match query,但它的表现并不像你想要的那样。
比较validate对multi_match
和query_string
的输出。
multi_match
(与运营商and
)将确保所有条款至少存在于一个字段中:
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
)将检查至少一个字段中是否存在EACH术语:
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
# }
所以你有几个选择来实现你的目标:
- 在使用
query_string
之前,准备搜索术语,删除通配符等内容 - 预填充搜索词以提取每个单词,然后为每个单词生成
multi_match
查询 - 在映射中使用
index_name
作为名称字段,将其数据索引到单个字段中,然后可以将其用于搜索。 (就像你自己的自定义all
字段):
如下:
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
。
您可以将multi-fields与path
参数一起使用,以使它们可以独立和一起搜索,如下所示:
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
# }
在firstname
搜索john AND smith
不起作用:
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
# }
但搜索firstname
只是john
正常工作:
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,以防用户传递“OR”,“AND”和任何其他高级参数。
根据我的经验,使用反斜杠转义特殊字符是一种简单而有效的解决方案。该列表可以在文档http://lucene.apache.org/core/4_5_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description中找到,加上AND / OR / NOT / TO。
我认为“匹配”查询是您正在寻找的:
“匹配查询系列不会通过”查询解析“过程。它不支持字段名称前缀,通配符或其他”高级“功能。因此,它失败的可能性非常小/不存在,当它只是分析并运行该文本作为查询行为(通常是文本搜索框所做的)时,它提供了一个很好的行为“
http://www.elasticsearch.org/guide/reference/query-dsl/match-query.html
现在你可以在cross_fields中使用multi_match
类型
GET /_validate/query?explain
{
"query": {
"multi_ma以上是关于多字段,多字,匹配没有query_string的主要内容,如果未能解决你的问题,请参考以下文章
es查询term,match,match_phase,query_string的区别
使用正则表达式将字段拆分为数组的 Bash 脚本用于多字符分隔符