带有嵌套DBRef的Mongo查找

时间:2019-09-15 04:19:45

标签: mongodb dbref

我在MongoDB中有一个名为“ post”的集合,其中包含指向“作者”的DBRef的列表,而该列表又将DBRef指向了一个“媒体”集合。

检索帖子时,我希望获取整个帖子,包括对象中的所有作者和媒体。

例如,这是我的收藏集:

post:
{
    "_id" : ObjectId("5d7db7af49c5e277395871bd"),
    "authors" : [
        DBRef("author", ObjectId("5d7daaab49c5e277395871ba")),
        DBRef("author", ObjectId("5d7daaab49c5e277395871bb"))
    ]
}

author:
[{
    "_id" : ObjectId("5d7daaab49c5e277395871ba"),
    "name" : "author 1",
    "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b8"))
},
{
    "_id" : ObjectId("5d7daaab49c5e277395871bb"),
    "name" : "author 2",
    "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b9"))
}]

media:
[{
    "_id" : ObjectId("5d7daa2049c5e277395871b8"),
    "url" : "http://image.com/1",
    "type" : "png"
},
{
    "_id" : ObjectId("5d7daa2049c5e277395871b9"),
    "url" : "http://image.com/2",
    "type" : "png"
}]

我希望查询得到以下结果:

post:
{
    "_id" : ObjectId("5d7db7af49c5e277395871bd"),
    "authors" : [
            {
                "_id" : ObjectId("5d7daaab49c5e277395871ba"),
                "name" : "author 1",
                "media" : {
                    "_id" : ObjectId("5d7daaab49c5e277395871ba"),
                    "name" : "author 1",
                    "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b8"))
                }
            },
            {
                "_id" : ObjectId("5d7daaab49c5e277395871bb"),
                "name" : "author 2",
                "media" : {
                    "_id" : ObjectId("5d7daaab49c5e277395871bb"),
                    "name" : "author 2",
                    "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b9"))
                }
            }
    ]
}

到目前为止,我有以下查询,其中包含帖子中的作者,但我还需要在作者中检索媒体的帮助。

current query:

db.post.aggregate([
{
    $project: { 
        authors: {
          $map: { 
             input: { 
                  $map: {
                      input:"$authors",
                      in: {
                           $arrayElemAt: [{$objectToArray: "$$this"}, 1]
                      },
                  }
             },
             in: "$$this.v"}},
        }

}, 
{
    $lookup: {
        from:"author", 
        localField:"authors",
        foreignField:"_id", 
        as:"authors"
    }
},
])

current result:

{
    "_id" : ObjectId("5d7db7af49c5e277395871bd"),
    "authors" : [
        {
            "_id" : ObjectId("5d7daaab49c5e277395871ba"),
            "name" : "author 1",
            "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b8"))
        },
        {
            "_id" : ObjectId("5d7daaab49c5e277395871bb"),
            "name" : "author 2",
            "media" : DBRef("media", ObjectId("5d7daa2049c5e277395871b9"))
        }
    ]
}

1 个答案:

答案 0 :(得分:1)

先尝试$unwind,然后再通过ID $goup

您可以这样做

db.post.aggregate([{
    $project: {
        authors: {
            $map: {
                input: {
                    $map: {
                        input: "$authors",
                        in: {
                            $arrayElemAt: [{
                                $objectToArray: "$$this"
                            }, 1]
                        },
                    }
                },
                in: "$$this.v"
            }
        },
    }
}, {
    $lookup: {
        from: "author",
        localField: "authors",
        foreignField: "_id",
        as: "authors"
    }
}, {
    $unwind: "$authors"
}, {
    $project: {
        "authors.media": {
            $arrayElemAt: [{
                $objectToArray: "$authors.media"
            }, 1]
        },
        "authors._id": 1,
        "authors.name": 1
    }
}, {
    $lookup: {
        from: "media",
        localField: "authors.media.v",
        foreignField: "_id",
        as: "authors.media"
    }
}, {
    $unwind: {
        path: "$authors.media",
        preserveNullAndEmptyArrays: true
    }
}, {
    $group: {
        _id: "$_id",
        authors: {
            $push: "$authors"
        }
    }
}]).pretty()

这是结果


    "_id" : ObjectId("5d7db7af49c5e277395871bd"),
    "authors" : [
        {
            "_id" : ObjectId("5d7daaab49c5e277395871ba"),
            "name" : "author 1",
            "media" : {
                "_id" : ObjectId("5d7daa2049c5e277395871b8"),
                "url" : "http://image.com/1",
                "type" : "png"
            }
        },
        {
            "_id" : ObjectId("5d7daaab49c5e277395871bb"),
            "name" : "author 2",
            "media" : {
                "_id" : ObjectId("5d7daa2049c5e277395871b9"),
                "url" : "http://image.com/2",
                "type" : "png"
            }
        }
    ]
}

您可以在中间阶段使用$project更改格式

还有什么
$unwind可以与option一起使用。下面的$ unwind操作使用prepareNullAndEmptyArrays选项在输出中包括那些缺少size字段,空值或空数组的文档。

[
   { $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }
]

这是documents