MongoDB поиск с глубоко вложенными массивами - PullRequest
0 голосов
/ 26 января 2020

У меня есть вопрос, где я не могу найти решение.

У меня есть коллекция "medium" с массивом с глубоким вложением, в котором ссылка через 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 ".

Теперь моя проблема , Я хочу создать агрегированный запрос со ссылкой на все objectIds в Person.

Я попробовал несколько способов сейчас, но поиск не будет совпадать вообще:

Это то, что я пытался прямо сейчас, но 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
    }
);

Может кто-нибудь помочь, пожалуйста?

1 Ответ

0 голосов
/ 27 января 2020

Попробуйте этот запрос:

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-Playground

...