Node.js 如何在mongoose中组合嵌套$lookup 3级别?

Node.js 如何在mongoose中组合嵌套$lookup 3级别?,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我想将单独的集合合并为1个json,但嵌套$lookup中存在一些问题 这是我的示例集合。 集合包订阅: [ { "_id": "1", "package_name": "Small", "package_desc": "AAA", "package_price": 10 }, { "_id": "2", "package_name": "Medium", "p

我想将单独的集合合并为1个json,但嵌套$lookup中存在一些问题

这是我的示例集合。 集合包订阅:

[
    {
        "_id": "1",
        "package_name": "Small",
        "package_desc": "AAA",
        "package_price": 10
    },
    {
        "_id": "2",
        "package_name": "Medium",
        "package_desc": "BBB",
        "package_price": 20    
    }
收集软件包\u模块:

{
    "_id" : 1,
    "subscription_id" : 1,
    "billing_model_id" : 1,
    "module_id" : 1,
    "created_at" : ISODate("2019-06-17T07:59:43.199Z"),
}
{
    "_id" : 2,
    "subscription_id" : 1,
    "billing_model_id" : 3,
    "module_id" : 2,
    "created_at" : ISODate("2019-06-17T08:00:37.464Z"),
}
{
    "_id" : 3,
    "subscription_id" : 2,
    "billing_model_id" : 2,
    "module_id" : 1,
    "created_at" : ISODate("2019-06-17T08:00:56.610Z"),
}
{
    "_id" : 4,
    "subscription_id" : 2,
    "billing_model_id" : 4,
    "module_id" : 2,
    "created_at" : ISODate("2019-06-17T08:01:29.667Z"),
}
收集模块:

{
    "_id" : 1,
    "module_name" : "Call",
    "status" : "Active",
}
{
    "_id" : 2,
    "module_name" : "SMS",
    "status" : "Active",
}
收费模式

{
    "_id" : 1,
    "unit_count" : "Menit",
    "counter" : 2000,
},
{
    "_id" : 2,
    "unit_count" : "Menit",
    "counter" : 3000,
}
{
    "_id" : 3,
    "unit_count" : "SMS",
    "counter" : 3000,
},
{
    "_id" : 4,
    "unit_count" : "SMS",
    "counter" : 5000,
}
这是我尝试解决这个问题的代码,但没有达到预期的效果

Package_subscription
            .aggregate([
                {
                    $lookup: {
                            from: "o_package_modules",
                            localField: "_id",
                            foreignField: "subscription_id",
                            as: "package_modules"
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $lookup: {
                        from: "o_modules",
                        localField: "package_modules.module_id",
                        foreignField: "_id",
                        as: 'module'
                    }
                },
                {
                    $lookup: {
                        from: "o_billing_models",
                        localField: "package_modules.billing_model_id",
                        foreignField: "_id",
                        as: 'billing_module'
                    }
                }
            ])            
            .exec()                        
            .then((pricing) => {                
                res.json(pricing)                
            })
            .catch((err) => {
                res.send(err)
            })
我预计结果是:

[
    {
        "_id": "1",
        "package_name": "Small",
        "package_desc": "AAA",
        "package_price": 10,        
        "package_modules": [
            {
                "_id": 1,
                "subscription_id": 1,
                "billing_model": {
                        "_id": 1,
                        "unit_count": "Menit",
                        "counter": 2000
                    },
                "module": {
                        "_id": 1,
                        "module_name": "Call",
                        "status": "Active"
                    },
                "created_at": "2019-06-17T07:59:43.199Z",
            },
            {
                "_id": 2,
                "subscription_id": 1,
                "billing_model": {
                        "_id": 3,
                        "unit_count": "SMS",
                        "counter": 3000
                    },
                "module": {
                        "_id": 2,
                        "module_name": "SMS",
                        "status": "Active"
                    },
                "created_at": "2019-06-17T08:00:37.464Z",
            }
        ]
    },
    {
        "_id": 2,
        "package_name": "Medium",
        "package_desc": "BBB",
        "package_price": 20,
        "package_modules": [
            {
                "_id": 3,
                "subscription_id": 2,
                "billing_model": {
                        "_id": 2,
                        "unit_count": "Menit",
                        "counter": 3000
                    },
                "module": {
                        "_id": "1",
                        "module_name": "Call",
                        "status": "Active"
                    },
                "created_at": "2019-06-17T08:01:29.667Z",
            },
            {
                "_id": 4,
                "subscription_id": 2,
                "billing_model": {
                        "_id": 4,
                        "unit_count": "SMS",
                        "counter": 5000
                    },
                "module": {
                        "_id": 2,
                        "module_name": "SMS",
                        "status": "Active"
                    },
                "created_at": "2019-06-17T08:01:50.285Z",
            }
        ]
    }
]
但我的代码的输出是:

[
    {
        "_id": "1",
        "package_name": "Small",
        "package_desc": "AAA",
        "package_price": 10,        
        "package_modules": {
                "_id": 1,
                "subscription_id": 1,
                "billing_model_id": 1
                "module_id": 1                 
                "created_at": "2019-06-17T07:59:43.199Z",
            },            
        },
        "billing_model": [
            {
                "_id": 1,
                "unit_count": "Menit",
                "counter": 2000
            },
        ],

        "module": [
            {
                "_id": 1,
                "module_name": "Call",
                "status": "Active"
            }
        ]
    },
    {
        "_id": "1",
        "package_name": "Small",
        "package_desc": "AAA",
        "package_price": 10,        
        "package_modules": {
                "_id": 2,
                "subscription_id": 2,
                "billing_model_id": 3
                "module_id": 2                 
                "created_at": "2019-06-17T07:59:43.199Z",
            },            
        },
        "billing_model": [
            {
                "_id": 3,
                "unit_count": "SMS",
                "counter": 3000
            },
        ],

        "module": [
            {
                "_id": 2,
                "module_name": "SMS",
                "status": "Active"
            }
        ]
    }
    ..........
    // And medium where is loop again
]


我认为您的代码中存在多个问题

  • $lookup
    阶段,您需要将
    设置为
    软件包模块。计费模块
    软件包模块。模块
    而不是
    计费模块
    模块
    ,依此类推,这样,它就变成了
    package\u模块
    对象的字段,而不是单独的对象本身

  • 在每个
    $lookup
    阶段之后,您需要
    展开
    ,因为
    $lookup
    返回一个数组而不是一个对象

  • 您需要在
    聚合
    管道的末尾
    $group
    将一个订阅的所有
    打包模块
    推送到一个阵列中

  • 在解决了上述所有问题之后,, 您的聚合管道应如下所示:

    Package_subscription
            .aggregate([
                {
                    $lookup: {
                            from: "o_package_modules",
                            localField: "_id",
                            foreignField: "subscription_id",
                            as: "package_modules"
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $lookup: {
                        from: "o_modules",
                        localField: "package_modules.module_id",
                        foreignField: "_id",
                        as: 'package_modules.module'
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules.module",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $lookup: {
                        from: "o_billing_models",
                        localField: "package_modules.billing_model_id",
                        foreignField: "_id",
                        as: 'package_modules.billing_module'
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules.billing_module",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $group: {
                        _id: "$_id",
                        package_modules : {$push : "$package_modules"},
                        package_name: {$first . : "$package_name"},
                        package_desc: {$first . : "$package_desc"},
                        package_price: {$first . : "$package_price"}
                    }
                }
            ])            
            .exec()                        
            .then((pricing) => {                
                res.json(pricing)                
            })
            .catch((err) => {
                res.send(err)
            })
    
    最后一个
    $group
    阶段中的
    $push
    将把所有
    封装模块组合成一个阵列。我想这就是你最后想要的


    我希望这对您有用。

    我认为您的代码中存在多个问题

  • $lookup
    阶段,您需要将
    设置为
    软件包模块。计费模块
    软件包模块。模块
    而不是
    计费模块
    模块
    ,依此类推,这样,它就变成了
    package\u模块
    对象的字段,而不是单独的对象本身

  • 在每个
    $lookup
    阶段之后,您需要
    展开
    ,因为
    $lookup
    返回一个数组而不是一个对象

  • 您需要在
    聚合
    管道的末尾
    $group
    将一个订阅的所有
    打包模块
    推送到一个阵列中

  • 在解决了上述所有问题之后,, 您的聚合管道应如下所示:

    Package_subscription
            .aggregate([
                {
                    $lookup: {
                            from: "o_package_modules",
                            localField: "_id",
                            foreignField: "subscription_id",
                            as: "package_modules"
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $lookup: {
                        from: "o_modules",
                        localField: "package_modules.module_id",
                        foreignField: "_id",
                        as: 'package_modules.module'
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules.module",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $lookup: {
                        from: "o_billing_models",
                        localField: "package_modules.billing_model_id",
                        foreignField: "_id",
                        as: 'package_modules.billing_module'
                    }
                },
                {
                    $unwind: {
                        path: "$package_modules.billing_module",
                        preserveNullAndEmptyArrays: true                        
                    }
                },
                {
                    $group: {
                        _id: "$_id",
                        package_modules : {$push : "$package_modules"},
                        package_name: {$first . : "$package_name"},
                        package_desc: {$first . : "$package_desc"},
                        package_price: {$first . : "$package_price"}
                    }
                }
            ])            
            .exec()                        
            .then((pricing) => {                
                res.json(pricing)                
            })
            .catch((err) => {
                res.send(err)
            })
    
    最后一个
    $group
    阶段中的
    $push
    将把所有
    封装模块组合成一个阵列。我想这就是你最后想要的

    我希望这对你有用