MongoDB查询嵌入式文档数组

时间:2017-06-03 18:47:40

标签: node.js mongodb

我有以下文件:

{
    "_id" : ObjectId("59299670266cc82a042f3817"),
    "_userId" : ObjectId("590a08dba07c1a1bee87b310"),
    "name" : "My home",
    "floors" : [ 
        {
            "_id" : ObjectId("59299670266cc82a042f4541"),
            "name" : "Floor 1",
            "rooms" : [ 
                {
                    "_id" : ObjectId("59299670266cc82a042f4551"),
                    "name" : "Room 1",
                    "devices" : [
                        {
                            "_id" : ObjectId("59299670266cc82a042f4561"),
                            "name" : "Device 1"
                        },
                        {
                            "_id" : ObjectId("59299670266cc82a042f4562"),
                            "name" : "Device 2"
                        }
                    ]
                },
                {
                    "_id" : ObjectId("59299670266cc82a042f4552"),
                    "name" : "Room 2",
                    "devices" : [
                        {
                            "_id" : ObjectId("59299670266cc82a042f4563"),
                            "name" : "Device 3"
                        },
                        {
                            "_id" : ObjectId("59299670266cc82a042f4564"),
                            "name" : "Device 4"
                        }
                    ]
                }
            ]
        },
        {
            "_id" : ObjectId("59299670266cc82a042f4542"),
            "name" : "Floor 2",
            "rooms" : [ 
                {
                    "_id" : ObjectId("59299670266cc82a042f4553"),
                    "name" : "Room 1",
                    "devices" : [
                        {
                            "_id" : ObjectId("59299670266cc82a042f4565"),
                            "name" : "Device 5"
                        },
                        {
                            "_id" : ObjectId("59299670266cc82a042f4566"),
                            "name" : "Device 6"
                        }
                    ]
                },
                {
                    "_id" : ObjectId("59299670266cc82a042f4554"),
                    "name" : "Room 2",
                    "devices" : [
                        {
                            "_id" : ObjectId("59299670266cc82a042f4567"),
                            "name" : "Device 7"
                        },
                        {
                            "_id" : ObjectId("59299670266cc82a042f4568"),
                            "name" : "Device 8"
                        }
                    ]
                }
            ]
        }
    ]
}

我想获得所有设备的列表:

[
    {
        "_id" : ObjectId("59299670266cc82a042f4561"),
        "name" : "Device 1"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4562"),
        "name" : "Device 2"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4563"),
        "name" : "Device 3"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4564"),
        "name" : "Device 4"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4565"),
        "name" : "Device 5"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4566"),
        "name" : "Device 6"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4567"),
        "name" : "Device 7"
    },
    {
        "_id" : ObjectId("59299670266cc82a042f4568"),
        "name" : "Device 8"
    }
]

MongoDB有可能吗?

我已尝试使用聚合和{ $unwind: $floors.rooms.devices }

{ $unwind: $floors }
{ $unwind: $floors.rooms }
{ $unwind: $floors.rooms.devices }

但输出始终为空。我不知道我是否会以$ unwind取得我想要的输出。

因为我也在使用聚合作为其他东西,所以解决它会很好。

2 个答案:

答案 0 :(得分:1)

您可以使用$reduce收集3.4版本单个文档中所有楼层内所有房间内的所有设备。

以下查询有两个部分:inner reduce和outer reduce。

内部缩减将收集所有设备,$reduc一次一个房间,并与单个楼层元素中的前一个房间的设备阵列连接。

内部缩减的输出通过管道连接到外部$reduce到所有楼层的连接设备。

这样的东西
db.collection.aggregate(
    [{
        "$project": {
            "_id": 0,
            "devices": {
                "$reduce": {
                    "input": "$floors",
                    "initialValue": [],
                    "in": {
                        "$concatArrays": [
                            "$$value",
                            {
                                "$reduce": {
                                    "input": "$$this.rooms",
                                    "initialValue": [],
                                    "in": {
                                        "$concatArrays": [
                                            "$$value",
                                            "$$this.devices"
                                        ]
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }]
)

对于MongoDB版本< 3.4

您可以使用以下管道。在preserveNullAndEmptyArrays上使用$unwind选项可防止管道在以下任何数组丢失,空或空时删除文档。

db.collection.aggregate(    
    [
      { "$unwind": "$floors" },
      { "$unwind": "$floors.rooms" },
      { "$unwind": "$floors.rooms.devices" },
      { "$group":{ "_id":"$_id", "devices":{ "$push":"$floors.rooms.devices"} } }
    ]
)

答案 1 :(得分:1)

我认为你正在寻找这个:

db.collection.aggregate([
{$match: {}},
{$unwind: "$floors"},    
{$unwind: "$floors.rooms"},
{$unwind: "$floors.rooms.devices"},
{$group: {
    _id: "$floors.rooms._id",
    d1: {$push: "$floors.rooms.devices"}
}},   
{$unwind:"$d1"},
{$group: {
    _id: "ignore-me",
    devices: {$push: "$d1"}
}} 

]).pretty();