在双嵌套数组 MongoDB 中查找

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29071748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:20:57  来源:igfitidea点击:

Find in Double Nested Array MongoDB

mongodbmongodb-queryaggregation-framework

提问by Ali Kianinejad

I have this Collection in mongodb

我在 mongodb 中有这个 Collection

{
"_id" : "777",
"someKey" : "someValue",
"someArray" : [
    {
        "name" : "name1",
        "someNestedArray" : [
            {
                "name" : "value"
            },
            {
                "name" : "delete me"
            }
        ]
    }
  ]
}

I want to find document based on someArray.someNestedArray.name but i can't find any useful link all search result about update nested array i am trying this but return nothing

我想找到基于 someArray.someNestedArray.name 的文档,但我找不到任何有用的链接所有关于更新嵌套数组的搜索结果我正在尝试这个但什么都不返回

db.mycollection.find({"someArray.$.someNestedArray":{"$elemMatch":{"name":"1"}}})
db.mycollection.find({"someArray.$.someNestedArray.$.name":"1"})

and Some thing else

和其他一些东西

how can i find by element in double nested array mongodb?

如何在双嵌套数组 mongodb 中按元素查找?

回答by Neil Lunn

In the simplest sense this just follows the basic form of "dot notation"as used by MongoDB. That will work regardless of which array member the inner array member is in, as long as it matches a value:

在最简单的意义上,这只是遵循MongoDB 使用的“点符号”的基本形式。无论内部数组成员在哪个数组成员中,只要它匹配一个值,这都将起作用:

db.mycollection.find({
    "someArray.someNestedArray.name": "value"
})

That is fine for a "single field" value, for matching multiple-fields you would use $elemMatch:

这对于“单个字段”值很好,用于匹配您将使用的多个字段$elemMatch

db.mycollection.find({
    "someArray": { 
        "$elemMatch": {
            "name": "name1",
            "someNestedArray": {
                "$elemMatch": {
                    "name": "value",
                    "otherField": 1
                }
            }
        }
    }
})

That matches the document which would contain something with a a field at that "path" matching the value. If you intended to "match and filter" the result so only the matched element was returned, this is not possible with the positional operator projection, as quoted:

这匹配包含与值匹配的“路径”字段的文档。如果您打算“匹配和过滤”结果,以便只返回匹配的元素,则使用位置运算符投影是不可能的,如引用

Nested Arrays

The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

嵌套数组

位置 $ 运算符不能用于遍历多个数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为 $ 占位符的替换是单个值

Modern MongoDB

现代 MongoDB

We can do this by applying $filterand $maphere. The $mapis really needed because the "inner" array can change as a result of the "filtering", and the "outer" array of course does not match the conditions when the "inner" was stripped of all elements.

我们可以通过申请$filter$map这里来做到这一点。这$map是真正需要的,因为“内部”数组可以作为“过滤”的结果而改变,而“外部”数组当然与“内部”被剥离所有元素时的条件不匹配。

Again following the example of actually having multiple properties to match within each array:

再次遵循在每个数组中实际具有多个要匹配的属性的示例:

db.mycollection.aggregate([
  { "$match": {
    "someArray": {
      "$elemMatch": {
         "name": "name1",
         "someNestedArray": {
           "$elemMatch": {
             "name": "value",
             "otherField": 1
           }
         }
       }
    }
  }},
  { "$addFields": {
    "someArray": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$someArray",
            "as": "sa",
            "in": {
              "name": "$$sa.name",
              "someNestedArray": {
                "$filter": {
                  "input": "$$sa.someNestedArray",
                  "as": "sn",
                  "cond": {
                    "$and": [
                      { "$eq": [ "$$sn.name", "value" ] },
                      { "$eq": [ "$$sn.otherField", 1 ] }
                    ]
                  }
                }
              }             
            }
          },
        },
        "as": "sa",
        "cond": {
          "$and": [
            { "$eq": [ "$$sa.name", "name1" ] },
            { "$gt": [ { "$size": "$$sa.someNestedArray" }, 0 ] }
          ]
        }
      }
    }
  }}
])

Therefore on the "outer" array the $filteractually looks at the $sizeof the "inner" array after it was "filtered" itself, so you can reject those results when the whole inner array does in fact match noting.

因此,在“外部”数组上,$filter实际上是在$size“过滤”后查看“内部”数组的 ,因此当整个内部数组实际上与注意匹配时,您可以拒绝这些结果。

Older MongoDB

较旧的 MongoDB

In order to "project" only the matched element, you need the .aggregate()method:

为了仅“投影”匹配的元素,您需要以下.aggregate()方法:

db.mycollection.aggregate([
    // Match possible documents
    { "$match": {
        "someArray.someNestedArray.name": "value"
    }},

    // Unwind each array
    { "$unwind": "$someArray" },
    { "$unwind": "$someArray.someNestedArray" },

    // Filter just the matching elements
    { "$match": {
        "someArray.someNestedArray.name": "value"
    }},

    // Group to inner array
    { "$group": {
        "_id": { 
            "_id": "$_id", 
            "name": "$someArray.name"
        },
        "someKey": { "$first": "$someKey" },
        "someNestedArray": { "$push": "$someArray.someNestedArray" }
    }},

    // Group to outer array
    { "$group": {
        "_id": "$_id._id",
        "someKey": { "$first": "$someKey" },
        "someArray": { "$push": {
            "name": "$_id.name",
            "someNestedArray": "$someNestedArray"
        }}
    }} 
])

That allows you to "filter" the matches in nested arrays for one or more results within the document.

这允许您为文档中的一个或多个结果“过滤”嵌套数组中的匹配项。

回答by Jitendra

You can also try something like below:

您也可以尝试以下操作:

db.collection.aggregate(
    { $unwind: '$someArray' },
    {
        $project: {
            'filteredValue': {
                $filter: {
                  input: "$someArray.someNestedArray",
                  as: "someObj",
                  cond: { $eq: [ '$$someObj.name', 'delete me' ] }
                }
            }
        }
    }
)