MongoDB - 从深层子文档中获取对象

时间:2016-09-06 15:40:13

标签: mongodb mongodb-query

如何从Array内的Array查询对象,并将其作为顶级对象获取?例如,请考虑以下记录。

{
  "subjects": [
         {
             "name": "English",
             "teachers": [
                  {
                    "name": "Mark"   /* Trying to get this object*/
                  },
                  {
                    "name": "John"
                  }
              ]
         }
   ]
}

我试图将以下对象作为顶级对象。

{
   "name": "Mark"
}

1 个答案:

答案 0 :(得分:1)

您需要使用aggregation框架来完成您所要求的工作。

在这里,我输入了你收藏的文件:foo。

> db.foo.find().pretty()

{
    "_id" : ObjectId("57ceed3d31484d5b491eaae9"),
    "subjects" : [
        {
            "name" : "English",
            "teachers" : [
                {
                    "name" : "Mark"
                },
                {
                    "name" : "John"
                }
            ]
        }
    ]
}

使用$ unwind解开我们的数组,然后我们进入聚合管道的第一阶段:

> db.foo.aggregate([
...     {$unwind: "$subjects"}
... ]).pretty()

{
    "_id" : ObjectId("57ceed3d31484d5b491eaae9"),
    "subjects" : {
        "name" : "English",
        "teachers" : [
            {
                "name" : "Mark"
            },
            {
                "name" : "John"
            }
        ]
    }
}

主题是一个长度为1的数组,所以这里唯一的区别就是少了一组[]数组括号。

我们需要再次放松。

> db.foo.aggregate([
...     {$unwind: "$subjects"},
...     {$unwind: "$subjects.teachers"}
... ]).pretty()

{
    "_id" : ObjectId("57ceed3d31484d5b491eaae9"),
    "subjects" : {
        "name" : "English",
        "teachers" : {
            "name" : "Mark"
        }
    }
}
{
    "_id" : ObjectId("57ceed3d31484d5b491eaae9"),
    "subjects" : {
        "name" : "English",
        "teachers" : {
            "name" : "John"
        }
    }
}

现在我们将长度为'2'的数组转换为两个单独的文档。第一个是subjects.teachers.name = Mark,第二个是subjects.teachers.name = John。

我们只想返回name = Mark的情况,因此我们需要在我们的管道中添加$ match阶段。

> db.foo.aggregate([
...     {$unwind: "$subjects"},
...     {$unwind: "$subjects.teachers"},
...     {$match: {"subjects.teachers.name": "Mark"}}
... ]).pretty()

{
    "_id" : ObjectId("57ceed3d31484d5b491eaae9"),
    "subjects" : {
        "name" : "English",
        "teachers" : {
            "name" : "Mark"
        }
    }
}

确定!现在我们只匹配名称为Mark的案例。

让我们添加一个$ project案例来塑造我们想要的输入。

> db.foo.aggregate([
...     {$unwind: "$subjects"},
...     {$unwind: "$subjects.teachers"},
...     {$match: {"subjects.teachers.name": "Mark"}},
...     {$project: {"name": "$subjects.teachers.name", "_id": 0}}
... ]).pretty()

{ "name" : "Mark" }