【问题标题】:Find in Double Nested Array MongoDB在双嵌套数组 MongoDB 中查找
【发布时间】:2015-05-18 06:25:23
【问题描述】:

我在 mongodb 中有这个集合

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

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

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

还有一些其他的

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

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

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

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

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

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

    这与包含与该值匹配的“路径”中的字段的文档相匹配。如果您打算“匹配和过滤”结果以便只返回匹配的元素,则位置运算符投影无法做到这一点,as quoted

    嵌套数组

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

    现代 MongoDB

    我们可以通过在此处应用$filter$map 来做到这一点。 $map 是真正需要的,因为“内部”数组可能会因“过滤”而发生变化,而“外部”数组当然与“内部”被剥离所有元素时的条件不匹配。

    再次按照实际在每个数组中匹配多个属性的示例:

    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 ] }
              ]
            }
          }
        }
      }}
    ])
    

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

    旧版 MongoDB

    为了只“投影”匹配的元素,您需要.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"
            }}
        }} 
    ])
    

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

    【讨论】:

    • 谢谢,这对于“单个字段”值来说很好,对于匹配多个字段,您将使用 $elemMatch 这一行澄清了elemMatch 的确切用法,
    • 您的回答将改变我的项目!
    【解决方案2】:

    你也可以试试下面的方法:

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

    【讨论】:

    • 谢谢你的救命恩人!!!
    猜你喜欢
    • 2017-09-30
    • 1970-01-01
    • 2022-11-11
    • 2015-06-20
    • 2023-02-01
    • 1970-01-01
    • 2020-12-18
    • 2021-08-27
    相关资源
    最近更新 更多