如何使用mongoose $ lookup运算符进行查找链接,然后对结果进行分组?

时间:2017-12-08 11:15:10

标签: node.js mongodb mongoose

让我们考虑我有三个伪集合,如下面的

  

用户

{ "_id" : ObjectId("5a2a2c3dcf7961800e44dfc9"), "uid" : 1234, 
     "name" : "ashish", "email" : "info@gmail.com" }, 
{ "_id" : ObjectId("5a2a2c51cf7961800e44dfca"), "uid" : 1235, 
     "name" : "swapnil", "email" : "info@femail.com" }
  

bank_details

{ "_id" : ObjectId("5a2a2c9bcf7961800e44dfcb"), "uid" : 1234, "acc_no" : 1111 }, 
{ "_id" : ObjectId("5a2a2cc9cf7961800e44dfcc"), "uid" : 1234, "acc_no" : 2222 },
{ "_id" : ObjectId("5a2a2cd7cf7961800e44dfcd"), "uid" : 1235, "acc_no" : 3333 }, 
{ "_id" : ObjectId("5a2a2cdccf7961800e44dfce"), "uid" : 1235, "acc_no" : 4444 }
  

银行

{ "_id" : ObjectId("5a2a2d05cf7961800e44dfcf"), "acc_no" : 1111, "balance" : 100 }, 
{ "_id" : ObjectId("5a2a2d10cf7961800e44dfd0"), "acc_no" : 2222, "balance" : 200 }, 
{ "_id" : ObjectId("5a2a2d19cf7961800e44dfd1"), "acc_no" : 3333, "balance" : 300 }, 
{ "_id" : ObjectId("5a2a2d21cf7961800e44dfd2"), "acc_no" : 4444, "balance" : 400 }
  

我希望输出如下

{ "_id" : ObjectId("5a2a2c3dcf7961800e44dfc9"), "uid" : "1234", 
  "name" : "ashish", "email" : "info@gmail.com" ,
bank_details: [{
  acc_no:'1111',
  balance:'100'
},{
  acc_no:'2222',
  balance:'200'
}]}

对于每个用户个人资料,我确信可以使用$lookup$group运算符完成此操作,但我无法实现,我尝试使用多种方式执行此操作。任何人都可以为所需结果编写一个示例查询。

我正在尝试使用NodeJs中的mongoose编写查询

2 个答案:

答案 0 :(得分:1)

您可以使用两次查找和分组来完成此操作。查看以下查询:

db.getCollection('users').aggregate([{
  $lookup:
    {
      from: "bank_details",
      localField: "uid",
      foreignField: "uid",
      as: "bank_details"
    }
},
{   $unwind:{ path: "$bank_details", preserveNullAndEmptyArrays: true }},
{
    $lookup:{
        from: "bank", 
        localField: "bank_details.acc_no", 
        foreignField: "acc_no",
        as: "banks"
    }
},
{ $unwind: { path: "$banks", preserveNullAndEmptyArrays: true } },
{
    $group: {
        _id: "$_id",
        uid: {$first: "$uid"},
        name: {$first: "$name"},
        email: {$first: "$email"},
        bank_details: {$push: {acc_no: "$banks.acc_no", balance: "$banks.balance"}}
        }
    },
{ 
   "$project": {
      uid: 1,
      name: 1,
      email: 1,
      bank_details: { "$setDifference": [ "$bank_details", [{}, null] ] }
   }
}
])

结果:

/* 1 */
{
"_id" : ObjectId("5a2a2c51cf7961800e44dfca"),
"uid" : 1235.0,
"name" : "swapnil",
"email" : "info@femail.com",
"bank_details" : [ 
    {
        "acc_no" : 3333.0,
        "balance" : 300.0
    }, 
    {
        "acc_no" : 4444.0,
        "balance" : 400.0
    }
]
}

/* 2 */
{
"_id" : ObjectId("5a2a2c3dcf7961800e44dfc9"),
"uid" : 1234.0,
"name" : "ashish",
"email" : "info@gmail.com",
"bank_details" : [ 
    {
        "acc_no" : 1111.0,
        "balance" : 100.0
    }, 
    {
        "acc_no" : 2222.0,
        "balance" : 200.0
    }
 ]
}

答案 1 :(得分:0)

如果您不想丢失没有bank_details的用户,则必须在放松之前添加$project。通过" $放松"你展平bank_details数组和具有空数组的文档,因为没有任何东西可以解开,所以会消失。因此,您可以检查bank_detail数组是否为空并向字段添加零值:

db.getCollection('users').aggregate([{
        $lookup: {
            from: "bank_details",
            localField: "uid",
            foreignField: "uid",
            as: "bank_details"
        }
    },
    {
        $project: {
            "_id": "$_id",
            uid: "$uid",
            name: "$name",
            email: "$email",
            bank_details: {
                $cond: [{
                        $eq: ["$bank_details", []]
                    },
                    [{
                        _id: 0,
                        uid: {
                            $literal: NumberInt(0)
                        },
                        acc_no: {
                            $literal: NumberInt(0)
                        }
                    }], '$bank_details'
                ]
            }
        }
    },
    {
        $unwind: "$bank_details"
    },
    {
        $lookup: {
            from: "bank",
            localField: "bank_details.acc_no",
            foreignField: "acc_no",
            as: "banks"
        }
    },
    {
        $project: {
            "_id": "$_id",
            uid: "$uid",
            name: "$name",
            email: "$email",
            bank_details: "$bank_details",
            banks: {
                $cond: [{
                        $eq: ["$banks", []]
                    },
                    [{
                        _id: 0,
                        acc_no: {
                            $literal: NumberInt(0)
                        },
                        balance: {
                            $literal: NumberInt(0)
                        }
                    }], '$banks'
                ]
            }
        }
    },

    {
        $unwind: "$banks"
    },
    {
        $group: {
            "_id": "$_id",
            uid: {
                $first: "$uid"
            },
            name: {
                $first: "$name"
            },
            email: {
                $first: "$email"
            },
            bank_details: {
                $push: {
                    acc_no: "$banks.acc_no",
                    balance: "$banks.balance"
                }
            }
        }
    }
])

此处是查询结果:

/* 1 */
{
    "_id" : ObjectId("5a2a83a53b3899dec93be178"),
    "uid" : 1239,
    "name" : "emil",
    "email" : "emil@femail.com",
    "bank_details" : [ 
        {
            "acc_no" : 0.0,
            "balance" : 0.0
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5a2a2c51cf7961800e44dfca"),
    "uid" : 1235,
    "name" : "swapnil",
    "email" : "info@femail.com",
    "bank_details" : [ 
        {
            "acc_no" : 3333,
            "balance" : 300
        }, 
        {
            "acc_no" : 4444,
            "balance" : 400
        }
    ]
}

/* 3 */
{
    "_id" : ObjectId("5a2a2c3dcf7961800e44dfc9"),
    "uid" : 1234,
    "name" : "ashish",
    "email" : "info@gmail.com",
    "bank_details" : [ 
        {
            "acc_no" : 1111,
            "balance" : 100
        }, 
        {
            "acc_no" : 2222,
            "balance" : 200
        }
    ]
}