arrays - Elasticsearch - 过滤其中(嵌套数组之一)和(所有嵌套数组)

标签 arrays elasticsearch nested

TL;DR - 如何检查其中之一全部嵌套数组满足指定条件?

我有一个文档。每个 document 都有一个嵌套的 outer 对象数组,它们本身有一个嵌套的 inner 对象列表。我需要对所有至少一个文档的外部嵌套对象匹配的文档执行过滤器。当我说匹配时,我的意思是所有 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 对象,则认为匹配。但更糟糕的是,内部对象需要考虑以一种条件逻辑方式(例如 SQL 中的 CASE)根据 type 进行不同的匹配。例如,如果 type 是术语 "Country" 那么 inner 对象将被认为匹配如果 匹配 是指定的国家代码,例如 ES。文档可能具有不同类型内部对象,并且不保证特定类型将存在。

来自命令式 (Java) 编程背景的我在弄清楚如何实现这种过滤方面遇到了难以置信的困难。我能想到的任何东西甚至都模糊地符合这种行为。到目前为止,我所拥有的只是过滤后的查询;

"filtered" : {
      "query" : {
        "match_all" : { }
      },
      "filter" : {
        "bool" : {
          "should" : {
            "missing" : {
              "field" : "outer.inner.type"
            }
    }}}}
}

那么,问题是……

我如何过滤到具有至少一个 outer 对象且具有所有 inner 对象匹配的文档基于内部对象的类型

根据要求提供更多详细信息-

示例文档 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 code> 对象会麻烦它们的 inner 对象完全匹配。如果我们希望第二个 outer 对象匹配,那么所有三个 inner 都需要匹配。请注意,在第三个inner 中有一个额外的type。这会导致这样一种情况:如果存在一个类型,那么它需要匹配它else它不需要匹配,因为它缺席。

最佳答案

嵌套数组之一

让嵌套数组中的一个匹配某些条件变得非常简单。 nested filter如果嵌套对象数组中的任何一个与指定的内部过滤器匹配,则计算结果为匹配/真。例如,给定一个 outer 对象数组,其中一个对象的字段 match 的值为 "matching" 将考虑以下内容是的。

"nested": {
   "path": "outer",
   "filter": {
       "term" : { "match" : "matching" } 
   }
}

如果 其中一个 嵌套的 outer 对象有一个名为 match 且值为 的字段,则以上内容将被视为真实/匹配“匹配”

所有嵌套数组

只有当数组中的所有嵌套对象匹配时才认为嵌套过滤器匹配更有趣。事实上,这是不可能的。但是考虑到如果只有一个嵌套对象与过滤器匹配就被认为是匹配的,我们可以颠倒逻辑并说“如果嵌套对象的没有 匹配”实现我们所需要的。例如,给定一个嵌套的 outer.inner 对象数组,其中所有这些对象都有一个字段 match,其值为 "matching",如下所示将被认为是真实的。

"not" : {
   "nested": {
      "path": "outer.inner",
      "filter": {
          "not" : {
              "term" : { "match" : "matching" } 
          }
      }
   }
}

以上将被认为是真实的/匹配的,因为没有嵌套的outer.inner对象(双重否定)有名为 match 的字段,值为 "matching"。当然,这与所有嵌套内部对象具有匹配字段且值为“匹配”.

缺少任何嵌套对象

您无法使用传统的 missing filter 检查是否缺少包含嵌套对象的字段.这是因为嵌套对象实际上根本不在文档中,它们存储在其他地方。因此 missing filters将永远被认为是真实的。但是,您可以做的是检查 match_all 过滤器是否不返回这样的结果;

"not": {
   "nested": {
      "path": "outer",
      "filter": {
          "match_all": {}
       }
    }
 }

如果 match_all 没有找到结果,则这被认为是正确的/匹配的。

关于arrays - Elasticsearch - 过滤其中(嵌套数组之一)和(所有嵌套数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32608969/

相关文章:

arrays - 使用 .each 在交易数组中找到最小的负数和最小的正数

node.js - 如何在 ExpressJS 上使用 ElasticSearch geo_distance

python - 嵌套类的范围?

elasticsearch - Elasticsearch词查询不匹配特殊字符

elasticsearch - kibana 是否使用 SSR?

python - 使用 pandas 从嵌套的 json 转换为 csv

javascript - Vue.js + Vuex : How to mutate nested item state?

javascript - 你如何在javascript中 'search'数组?

php - "Notice: Undefined variable"、 "Notice: Undefined index"、 "Warning: Undefined array key"和 "Notice: Undefined offset"使用 PHP

arrays - Scala 连接数组并减少值