Elasticsearch - 过滤其中(嵌套数组之一)和(所有嵌套数组)
Elasticsearch - Filter where (one of nested array) and (all of nested array)
TL;DR - 如何检查 one-of 和 all- of 个嵌套数组满足指定条件?
我有一个document
。每个 document
都有一个嵌套的 outer
对象数组,它们本身有一个嵌套的 inner
对象列表。我需要对所有 至少有一个 文档的 outer
嵌套对象匹配的所有文档执行过滤器。当我说匹配时,我的意思是 all 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"
,那么如果 match
是指定的国家/地区代码,例如 ES
,则 inner
对象将被视为匹配。一个文档可能有 inner
个不同 type
的对象,并且不能保证特定类型将存在。
来自命令式 (Java) 编程背景,我在弄清楚如何实现这种过滤方面遇到了难以置信的麻烦。我能想到的任何东西甚至都模糊地符合这种行为。到目前为止,我只有过滤后的查询;
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"bool" : {
"should" : {
"missing" : {
"field" : "outer.inner.type"
}
}}}}
}
那么,问题是……
我如何筛选出具有 至少一个 outer
对象且具有 all inner
的文档基于 inner
object?
的 type
的对象匹配
根据要求提供更多详细信息 -
示例文档JSON
{
"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
都需要匹配。注意第三个inner
中多了一个type
。这会导致 if 类型存在 then 它需要匹配 else它不需要匹配,因为它不存在。
好吧,这很傻,但这个查询似乎可以满足您的要求:
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
如果您需要一些逻辑解释,请告诉我;有点牵扯了。
嵌套数组之一
拥有其中一个嵌套数组匹配某些条件证明是非常简单的。如果嵌套对象数组中的任何一个与指定的内部过滤器匹配,则 nested filter 的计算结果为 matching/true。例如,给定一个包含 outer
个对象的数组,其中一个对象的字段 match
的值为 "matching"
,则以下内容将被视为 true。
"nested": {
"path": "outer",
"filter": {
"term" : { "match" : "matching" }
}
}
如果 其中一个 嵌套 outer
对象具有名为 match
且值为 "matching"
.
所有嵌套数组
如果所有数组中的嵌套对象都匹配,则只有嵌套过滤器才被视为匹配更有趣。事实上,这是不可能的。但是考虑到如果只有一个嵌套对象匹配过滤器就被认为是匹配的,我们可以反转逻辑并说 "If none of the nested objects don't match" 来实现我们需要的。例如,给定一个嵌套 outer.inner
对象的数组,其中所有这些对象都有一个值为 "matching"
的字段 match
,以下将被认为是正确的。
"not" : {
"nested": {
"path": "outer.inner",
"filter": {
"not" : {
"term" : { "match" : "matching" }
}
}
}
}
以上将被视为 true/matching 因为嵌套 outer.inner
对象的 none 不(双重否定)有一个名为 match
的字段,其值为 "matching"
。当然,这与 所有 嵌套 inner
对象具有字段 match
且值为 "matching"
.
缺少任何嵌套对象
您无法检查是否缺少包含嵌套对象的字段,使用传统的 missing filter. This is because nested objects aren't actually in the document at all, they are stored somewhere else. As such missing filters 将始终被视为 true。但是,您可以做的是检查 match_all
过滤器 returns 没有这样的结果;
"not": {
"nested": {
"path": "outer",
"filter": {
"match_all": {}
}
}
}
如果 match_all
没有找到结果,这将被视为 true/matching。
TL;DR - 如何检查 one-of 和 all- of 个嵌套数组满足指定条件?
我有一个document
。每个 document
都有一个嵌套的 outer
对象数组,它们本身有一个嵌套的 inner
对象列表。我需要对所有 至少有一个 文档的 outer
嵌套对象匹配的所有文档执行过滤器。当我说匹配时,我的意思是 all 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"
,那么如果 match
是指定的国家/地区代码,例如 ES
,则 inner
对象将被视为匹配。一个文档可能有 inner
个不同 type
的对象,并且不能保证特定类型将存在。
来自命令式 (Java) 编程背景,我在弄清楚如何实现这种过滤方面遇到了难以置信的麻烦。我能想到的任何东西甚至都模糊地符合这种行为。到目前为止,我只有过滤后的查询;
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"bool" : {
"should" : {
"missing" : {
"field" : "outer.inner.type"
}
}}}}
}
那么,问题是……
我如何筛选出具有 至少一个 outer
对象且具有 all inner
的文档基于 inner
object?
type
的对象匹配
根据要求提供更多详细信息 -
示例文档JSON
{
"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
都需要匹配。注意第三个inner
中多了一个type
。这会导致 if 类型存在 then 它需要匹配 else它不需要匹配,因为它不存在。
好吧,这很傻,但这个查询似乎可以满足您的要求:
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
如果您需要一些逻辑解释,请告诉我;有点牵扯了。
嵌套数组之一
拥有其中一个嵌套数组匹配某些条件证明是非常简单的。如果嵌套对象数组中的任何一个与指定的内部过滤器匹配,则 nested filter 的计算结果为 matching/true。例如,给定一个包含 outer
个对象的数组,其中一个对象的字段 match
的值为 "matching"
,则以下内容将被视为 true。
"nested": {
"path": "outer",
"filter": {
"term" : { "match" : "matching" }
}
}
如果 其中一个 嵌套 outer
对象具有名为 match
且值为 "matching"
.
所有嵌套数组
如果所有数组中的嵌套对象都匹配,则只有嵌套过滤器才被视为匹配更有趣。事实上,这是不可能的。但是考虑到如果只有一个嵌套对象匹配过滤器就被认为是匹配的,我们可以反转逻辑并说 "If none of the nested objects don't match" 来实现我们需要的。例如,给定一个嵌套 outer.inner
对象的数组,其中所有这些对象都有一个值为 "matching"
的字段 match
,以下将被认为是正确的。
"not" : {
"nested": {
"path": "outer.inner",
"filter": {
"not" : {
"term" : { "match" : "matching" }
}
}
}
}
以上将被视为 true/matching 因为嵌套 outer.inner
对象的 none 不(双重否定)有一个名为 match
的字段,其值为 "matching"
。当然,这与 所有 嵌套 inner
对象具有字段 match
且值为 "matching"
.
缺少任何嵌套对象
您无法检查是否缺少包含嵌套对象的字段,使用传统的 missing filter. This is because nested objects aren't actually in the document at all, they are stored somewhere else. As such missing filters 将始终被视为 true。但是,您可以做的是检查 match_all
过滤器 returns 没有这样的结果;
"not": {
"nested": {
"path": "outer",
"filter": {
"match_all": {}
}
}
}
如果 match_all
没有找到结果,这将被视为 true/matching。