首页 > 解决方案 > 具有深度嵌套数组的 MongoDB 查找

问题描述

我有一个找不到解决方案的问题。

我有一个带有深度嵌套数组的集合“介质”,其中通过 ObjectID 对人员集合的引用。

中等收藏:

{
    "title": "Test Medium",
        "mediumMetaData": {
        "metaData": [{
            "movietype": "movie",
            "year": 2019,
            "language": "german",
            "personInformation": {
                "actor": [{
                    "actors": "5e2c3b1daf0ba75b00415bb0"
                }],
                "director": [{
                    "directors": "5e2c3b1daf0ba75b00415bb0"
                }],
                "screenwriter": [{
                    "screenwriters": "5e2c3b1daf0ba75b00415bb0"
                }],
                "camera": [{
                    "cameras": "5e2c3b81af0ba75b00415bb1"
                }]
            }
        }]
    },
    "createdById": "5dcb108b59057b22702ecaa9"
}

人员集合应通过“ _id ”字段匹配。

现在我的问题。我想通过引用 Person 中的所有 objectId 来构建聚合查询。

我现在尝试了几种方法,但查找根本不匹配:

这是我现在尝试的,但是 actor-tag 一直是空的:前两个阶段正在工作,据我所知,我需要两个展开,每个数组部分一个。

db.getCollection("medium").aggregate(
    [
        { 
            "$match" : {
                "_id" : ObjectId("5e2c3d9002d512c71cda8006")
            }
        }, 
        { 
            "$unwind" : {
                "path" : "$mediumMetaData.metaData", 
                "preserveNullAndEmptyArrays" : false
            }
        }, 
        { 
            "$unwind" : {
                "path" : "$mediumMetaData.metaData.personInformation.actor", 
                "preserveNullAndEmptyArrays" : false
            }
        }, 
        { 
            "$lookup" : {
                "from" : "person", 
                "let" : {
                    "actor_id" : "$mediumMetaData.metaData.personInformation.actor.actors"
                }, 
                "pipeline" : [
                    {
                        "$match" : {
                            "$expr" : [
                                {
                                    "$eq" : [
                                        "$_id", 
                                        "$$$actor_id"
                                    ]
                                }
                            ]
                        }
                    }, 
                    {
                        "$project" : {
                            "_id" : 0.0
                        }
                    }
                ], 
                "as" : "actor1"
            }
        }
    ], 
    { 
        "allowDiskUse" : false
    }
);

有人可以帮忙吗?

标签: mongodbmongodb-queryaggregate

解决方案


试试这个查询:

db.medium.aggregate([{ $match: { "_id": ObjectId("5e2df451d02e05b69467d1bc") } },
{ $unwind: '$mediumMetaData.metaData' },
{
    $lookup:
    {
        from: "Person",
        let: {
            actor: "$mediumMetaData.metaData.personInformation.actor", director: "$mediumMetaData.metaData.personInformation.director",
            screenwriter: "$mediumMetaData.metaData.personInformation.screenwriter", camera: "$mediumMetaData.metaData.personInformation.camera"
        },
        pipeline: [
            {
                $project: {
                    name: 1,
                    personID: {
                        $let:
                        {
                            vars: { id: '$_id' },
                            in: { $toString: "$$id" }
                        }
                    }
                }
            },
            {
                $match:
                {
                    $expr:
                    {
                        $or:
                            [
                                { $in: ['$personID', "$$actor.actors"] },
                                { $in: ['$personID', "$$director.directors"] },
                                { $in: ['$personID', "$$screenwriter.screenwriters"] },
                                { $in: ['$personID', "$$camera.cameras"] }
                            ]
                    }
                }
            }, { $project: { personID: 0 } }
        ],
        as: "personInfo"
    }
}, { $unwind: { path: "$personInfo", preserveNullAndEmptyArrays: true } },
{ $group: { _id: '$_id', 'metaData': { $addToSet: '$mediumMetaData.metaData' },
          personInfo: { $push: '$personInfo' }, title: { $first: '$title' }, createdById: { $first: '$createdById' } } },
{ $project: { 'mediumMetaData.metaData': '$metaData', createdById: 1, title: 1, personInfo: 1 } }
])

注意:如果你 "actors": "5e2c3b1daf0ba75b00415bb0"/"directors": "5e2c3b1daf0ba75b00415bb0"ObjectId()而不是strings,那么你可以通过比较类似的东西来避免两个$project阶段pipeline{ $in: ['$_id', "$$actor.actors"] }

测试: MongoDB-游乐场


推荐阅读