当前位置: 首页 > 知识库问答 >
问题:

弹性搜索 - 过滤位置(嵌套数组之一)和(所有嵌套数组)

欧阳勇军
2023-03-14

太长别读-如何检查一个嵌套数组和所有嵌套数组是否满足指定的条件?

我有一个文档。每个文档都有一个嵌套的外部对象数组,这些对象本身有一个嵌套的内部对象列表。我需要对所有文档执行一个过滤器,其中至少有一个文档的外部嵌套对象匹配。当我说匹配时,我的意思是所有外部嵌套对象的内部对象以某种方式匹配。这里有一个示例映射供参考;

{ "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"
              }
    }}}}}}
}

如果文档没有< code >外部/内部对象,则认为它匹配。但更糟糕的是,内部对象需要被认为以一种条件逻辑方式(例如SQL中的< code>CASE)根据< code>type进行不同的匹配。例如,如果< code>type是术语< code >“Country”,那么如果< code>match是指定的国家代码,如< code>ES,则< code>inner对象将被视为匹配。文档可能具有不同< code >类型的< code >内部对象,并且不保证特定类型将存在。

我来自一个命令式(Java)编程背景,在弄清楚如何实现这种过滤时遇到了难以置信的困难。我想不出任何东西能与这种行为相匹配。到目前为止,我所有的是过滤查询;

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

所以,问题是...

如何过滤到至少有一个外部对象的文档,该对象具有基于内部对象的类型匹配的所有内部对象?

按要求提供更多详细信息-

{
    "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"
}

如果我们要提供"First Class"market和Country"GRB",那么上面的示例应该通过过滤器,因为两个外部对象中的第二个将被认为是匹配的,因为两个内部对象都匹配。但是,如果我们提供了国家/地区"GRB"和market"Elite",那么我们将不会返回此文档,因为外部对象都不会打扰它们的内部对象完全匹配。如果我们想让第二个外部对象匹配,那么所有三个内部都需要匹配。请注意,在第三个内部中有一个额外的类型。这会导致一种情况,如果一个类型存在,那么它需要与之匹配,否则它不需要匹配,因为它不存在。

共有2个答案

樊浩初
2023-03-14

嗯,这真是太棒了,但这个查询似乎可以满足您的需要:

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

如果您需要对逻辑进行一些解释,请告诉我;它有点牵扯。

通远
2023-03-14

让嵌套数组中的一个与某些条件匹配非常简单。如果任何嵌套对象数组与指定的内部筛选器匹配,则嵌套筛选器的计算结果为matching/true。例如,给定一个外部对象数组,其中一个对象的字段matchwith value ,则以下内容将被视为正确。

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

如果嵌套外部对象中有一个名为match>的字段,其值为 “matching”,则上述情况将被视为正确/匹配。

只有当数组中的所有嵌套对象都匹配时,才认为嵌套过滤器匹配。事实上,这是不可能的。但是,如果只有一个嵌套对象与过滤器匹配,则被视为匹配,我们可以颠倒逻辑,说“如果没有任何嵌套对象不匹配”,以实现我们需要的结果。例如,给定一个嵌套outer数组。内部对象,其中所有这些对象都有一个字段matchwith value“matching”,以下内容将被视为正确。

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

上述内容将被视为true/matching,因为所有嵌套的< code>outer.inner对象都没有(双重否定)名为< code>match的字段,其值为< code >“matching”。当然,这与所有具有值为< code >“匹配”的字段< code>match的嵌套< code>inner对象是一样的。

您不能使用传统的缺失过滤器检查包含嵌套对象的字段是否缺失。这是因为嵌套对象实际上根本不在文档中,它们存储在其他地方。因此,缺失的过滤器将始终被认为是真的。然而,您可以做的是检查match_all过滤器是否没有返回这样的结果;

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

如果match_all未找到结果,则认为这是真的/匹配的。

 类似资料:
  • 问题内容: TL; DR -我该如何检查是否 之一的 和 所有的 嵌套数组满足规定的标准是什么? 我有一个。每个对象都有一个嵌套对象数组,这些对象本身都有一个嵌套对象列表。我需要对所有文档中 至少一个嵌套对象匹配的文档执行过滤器。当我说的比赛,我的意思是 所有 的嵌套对象的对象以某种方式相匹配。这是一个示例映射,以供参考; 如果文档没有/ 对象,则认为是匹配的。但是,更糟糕的是,内部对象需要考虑以

  • 如何获得空数组和美国的结果和

  • 我已经为一个问题挣扎了一段时间,所以我想我应该通过stackoverflow来解决这个问题。 “我的文档类型”有一个标题、一个语言字段(用于筛选)和一个分组id字段(我省略了所有其他字段以保持重点) 搜索文档时,我希望找到包含标题中文本的所有文档。对于每个唯一的分组id,我只需要一个文档。 我一直在关注tophits聚合,从我所看到的情况来看,它应该能够解决我的问题。 对我的索引运行此查询时: 我

  • 我有一个弹性搜索索引集合,如下所示, 现在我需要通过将与其值匹配来搜索文档。(是一些字段,其值存储在中)例如。对于字段,如果它是,则应与上述文档匹配。 我尝试将其映射为嵌套对象,但我无法编写查询来搜索与其相应值匹配的2个或更多的键id。

  • 我在Elasticsearch中获得了大量数据。我的douments有一个名为“records”的嵌套字段,它包含一个包含多个字段的对象列表。 我希望能够从记录列表中查询特定的对象,因此我在查询中使用了inner_hits字段,但是这没有帮助,因为聚合使用大小0,所以没有返回结果。 我没有成功地使一个聚集只对inner_hits有效,因为无论查询是什么,聚集都返回记录中所有对象的结果。 这是我正在

  • 我正在使用spring数据elasticsearch和elasticsearch一起查询文档。我想对嵌套文档进行嵌套查询。 我有java版本: 而且 当我让spring数据进行映射时,我得到: 当我试图查询文档时,我遇到了经典的内部文档与嵌套文档的问题,它无法识别嵌套元素。 当我尝试更新映射以使用嵌套文档时,我得到“无法从非嵌套更改为嵌套”。 我是否应该告诉spring data es@Neste