简体   繁体   English

MongoDB查询嵌入式文档数组

[英]MongoDB query embedded document array

I have the following document: 我有以下文件:

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

And I would like to get a list of all devices: 我想获取所有设备的列表:

[
    {
        "_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"
    }
]

Is that possible with MongoDB? MongoDB有可能吗?

I've tried it with aggregate and { $unwind: $floors.rooms.devices } or 我已经尝试使用汇总和{ $unwind: $floors.rooms.devices }

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

but the output is always empty. 但输出始终为空。 I don't know if I would get the output I want with $unwind at all. 我不知道是否可以用$ unwind得到我想要的输出。

Because I'm also using aggregate for other things a solution with it would be nice. 因为我还在将聚合用于其他用途,所以有一个很好的解决方案。

You can use $reduce to collect all the devices inside all rooms across all floors in a single document in 3.4 version. 您可以使用$reduce在3.4版本的单个文档中收集所有楼层所有房间内的所有设备。

The below query has two parts inner reduce and outer reduce. 下面的查询有两个部分:内部归约和外部归约。

The inner reduce will collect all the devices, $reduc ing one room at a time and concatenating with the previous room's devices arrays in a single floor element. 内减少将收集所有的设备, $reduc荷兰国际集团一次在一个房间,在一个单一的地板单元前面的房间的设备阵列串联。

The output from the inner reduce is piped to the outer $reduce to concat devices across all floors. 内部reduce的输出通过管道传递到外部$reduce以连接所有楼层的设备。

Something like 就像是

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

For MongoDB Version < 3.4 对于MongoDB版本<3.4

You can use the below pipeline. 您可以使用以下管道。 Use preserveNullAndEmptyArrays option on $unwind to prevent pipeline from dropping documents when any of the below arrays is missing, null or empty. $unwind上使用preserveNullAndEmptyArrays选项可防止在缺少以下任何数组,null或为空时管道丢失文档。

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

I think you are looking for this: 我认为您正在寻找:

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM