TL; DR - 如何检查一个和全部嵌套数组是否符合指定条件?
我有document
。每个document
都有一个嵌套的outer
对象数组,这些对象本身有一个嵌套的inner
对象列表。我需要对至少一个文档的outer
嵌套对象匹配的所有文档执行过滤。当我说匹配时,我的意思是所有 outer
嵌套对象' inner
个对象以某种方式匹配。这是一个示例映射供参考;
{ "document" : {
"properties" : {
"name" : {
"type" : "string"
},
"outer" : {
"type" : "nested",
"properties" : {
"inner" : {
"type" : "nested",
"properties" : {
"match" : {
"type" : "string",
"index" : "not_analyzed"
},
"type" : {
"type" : "string",
"index" : "not_analyzed"
}
}}}}}}
}
如果文档没有outer
/ inner
个对象,则认为它们匹配。但是为了使事情变得更糟,需要根据type
以一种条件逻辑方式(例如SQL中的CASE
)来考虑内部对象的不同匹配。例如,如果type
是术语"Country"
,那么inner
对象将被视为匹配,如果match
是指定的国家/地区代码,例如ES
。文档可能包含inner
个type
个不同的对象,并且不保证存在特定类型。
来自命令式(Java)编程背景我在弄清楚如何实现这种过滤方面遇到了令人难以置信的麻烦。没有什么我能想到甚至模糊地匹配这种行为。到目前为止,我所拥有的只是过滤后的查询;
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"bool" : {
"should" : {
"missing" : {
"field" : "outer.inner.type"
}
}}}}
}
所以,问题是......
如何过滤到至少一个 outer
对象的文档,该对象具有基于{{1}匹配的所有 inner
个对象} type
对象?
进一步详情请求 -
inner
如果我们要提供{
"name":"First",
"outer":[
{
"inner":[
{"match":"ES","type":"Country"},
{"match":"Elite","type":"Market"}
]
},{
"inner":[
{"match":"GBR","type":"Country"},
{"match":"1st Class","type":"Market"},
{"match":"Admin","type":"Role"}
]
}
],
"lockVersion":0,"sourceId":"1"
}
市场和国家/地区"1st Class"
,上面的示例应通过过滤器,因为两个"GRB"
对象中的第二个会被视为匹配,因为两个outer
个对象都匹配。但是,如果我们提供了国家/地区inner
和市场"GRB"
,那么我们就不会返回此文档,因为"Elite"
个对象都不会打扰他们outer
对象完全匹配。如果我们希望第二个inner
对象匹配,那么所有三个outer
都需要匹配。请注意,第三个inner
中还有一个type
。这导致如果类型存在然后它需要匹配 else 它不需要匹配的情况因为它不存在
答案 0 :(得分:15)
一个符合某些条件的嵌套数组变得非常简单。如果任何嵌套对象数组与指定的内部过滤器匹配,则nested filter求值为匹配/ true。例如,给定一组outer
个对象,其中一个对象的字段match
的值为"matching"
,则以下内容将被视为真。
"nested": {
"path": "outer",
"filter": {
"term" : { "match" : "matching" }
}
}
如果其中一个嵌套outer
对象的字段名为match
且值为"matching"
,则上述内容将被视为真/匹配。
如果全部数组匹配中的嵌套对象更有趣,则只能将嵌套过滤器视为匹配。事实上,这是不可能的。但是,如果只有一个嵌套对象与过滤器匹配,则认为它是匹配的,我们可以反转逻辑并说“如果无嵌套对象不匹配”实现我们的需要。例如,给定一组嵌套的outer.inner
对象,其中所有这些对象的字段match
的值为"matching"
,以下内容将被视为真。
"not" : {
"nested": {
"path": "outer.inner",
"filter": {
"not" : {
"term" : { "match" : "matching" }
}
}
}
}
上述内容将被视为真/匹配,因为嵌套outer.inner
对象的无 不(双重否定)有一个名为{{1的字段值match
。当然,这与所有具有值"matching"
的字段inner
的嵌套match
对象相同。
使用传统的missing filter无法检查是否缺少包含嵌套对象的字段。这是因为嵌套对象实际上不是在文档中,它们存储在其他地方。因此missing filters将始终被视为真实。但是,您可以检查"matching"
过滤器是否返回没有这样的结果;
match_all
如果"not": {
"nested": {
"path": "outer",
"filter": {
"match_all": {}
}
}
}
未找到任何结果,则视为真/匹配。
答案 1 :(得分:3)
嗯,这很麻烦,但这个查询似乎可以做你想要的:
POST /test_index/_search
{
"query": {
"filtered": {
"filter": {
"nested": {
"path": "outer",
"filter": {
"bool": {
"must": [
{
"nested": {
"path": "outer.inner",
"filter": {
"bool": {
"must": [
{ "term": { "outer.inner.type": "Market" } },
{ "term": { "outer.inner.match": "1st Class" } }
]
}
}
}
},
{
"nested": {
"path": "outer.inner",
"filter": {
"bool": {
"must": [
{ "term": { "outer.inner.type": "Country" } },
{ "term": { "outer.inner.match": "GBR" } }
]
}
}
}
}
]
}
}
}
}
}
}
}
以下是我用来测试它的一些代码:
http://sense.qbox.io/gist/f554c2ad2ef2c7e6f5b94b1ddb907813370f4edc
如果您需要对逻辑进行一些解释,请告诉我。它有点牵扯。