Mongodb 汇总数组中某个字段的 $lookup

Mongodb aggrregate $lookup of a field inside array

我有一个包含 3 个集合的数据库。 第一个有一些参考其他文件的文件。

我需要查询 填充 项目 上的引用,以便加载需求。 我已经设法 $lookup requirements 数组,但我无法在 optionals 数组上使用它,因为它是数组的对象。请注意,它是一个具有引用和需要保留的额外字段的对象。

db.projects.findOne({user: ObjectId("602acb4b839ec6001d3ef506")})
{
        "_id" : ObjectId("6033cf8503ac5003f873cc9b"),
        "date" : 1614008193362,
        "requirements" : [
                ObjectId("6032c1249588930368d7603c"),
                ObjectId("6032c2dc9588930368d7603e")
        ],
        "status" : "ACTIVE",
        "hours" : 10,
        "expire" : 1629560197,
        "optionals" : [
                {
                        "requirement" : ObjectId("602e3104dd86db01c89dd47e"),
                        "amount" : 10
                },
                {
                        "requirement" : ObjectId("603171e89588930368d76038"),
                        "amount" : 10
                }
        ],
        "user" : ObjectId("602acb4b839ec6001d3ef506"),
        "__v" : 0
}
db.requirements.findOne()
{
        "_id" : ObjectId("602da2bbdd86db01c89dd479"),
        "date" : "1613602429148",
        "status" : "ACTIVE",
        "name" : "Test1",
        "description" : "Test1 description",
        "creator" : ObjectId("602acb4b839ec6001d3ef506"),
        "__v" : 0
}

这里指出了一个基于$lookup的解决方案,但我无法让它工作:MongoDB aggregate field in array of objects


db.project.aggregate([
    {
        $match : {user: ObjectId($interesting_user)}
    },
    {
        $lookup: {
            from: "requirements",
            localField: "requirements",
            foreignField: "_id",
            as: "requirements"
        }
    },
    {
        $lookup: {
            from: "requirements",
            localField: "optionals.requirement",
            foreignField: "_id",
            as: "optionals.requirement"
        }
    },
]).pretty()

我在这里遗漏了什么?浏览 MongoDb 文档没有给我任何解决方案

思路是$unwindoptionals既然是数组,就执行$lookup,然后$group就可以了。这一切只是为了保留amount字段!所以试试这个:

注意 我在测试数据的 requirements 集合中只创建了两个字段。您将获得案例中的所有其他剩余字段。

db.project.aggregate([
    {
        $match : {user: ObjectId("602acb4b839ec6001d3ef506")}
    },
    {
        $lookup: {
            from: "requirements",
            localField: "requirements",
            foreignField: "_id",
            as: "requirements"
        }
    },
    { $unwind: "$optionals" },
    {
        $lookup: {
            from: "requirements",
            let: { requirements: "$optionals.requirement" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq:["$_id", "$$requirements"]
                        }
                    }
                }
            ],
            as: "optionals.requirement"
        }
    },
    { $unwind: "$optionals.requirement" },
    {
        $group: { 
            _id: "$_id",
            date: { $first: "$date" },
            requirements: { $first: "$requirements" },
            status: { $first: "$status" },
            hours: { $first: "$hours" },
            expire: { $first: "$expire" },
            optionals: { $push: "$optionals" },
            user: { $first: "$user" }
        }
    }
]);

输出:

{
    "_id" : ObjectId("6033cf8503ac5003f873cc9b"),
    "date" : 1614008193362,
    "requirements" : [
        {
            "_id" : ObjectId("6032c1249588930368d7603c"),
            "name" : "Test1"
        },
        {
            "_id" : ObjectId("6032c2dc9588930368d7603e"),
            "name" : "Test2"
        }
    ],
    "status" : "ACTIVE",
    "hours" : 10,
    "expire" : 1629560197,
    "optionals" : [
        {
            "requirement" : {
                "_id" : ObjectId("602e3104dd86db01c89dd47e"),
                "name" : "Test3"
            },
            "amount" : 10
        },
        {
            "requirement" : {
                "_id" : ObjectId("603171e89588930368d76038"),
                "name" : "Test4"
            },
            "amount" : 10
        }
    ],
    "user" : ObjectId("602acb4b839ec6001d3ef506")
}