【问题标题】:Querying multiple lookups and aggregating data into single array based on condition in mongodb根据mongodb中的条件查询多个查找并将数据聚合到单个数组中
【发布时间】:2017-08-29 12:45:19
【问题描述】:

我在mongodb用户、账号、船、船员四个集合;都具有不同的数据结构。以下是示例:

用户合集

{
    "_id" : ObjectId("58b80a5f922a9656b78e86a7"),
    "email" : "bhargavksdn@gmail.com",
    "password" : "$2a$10$OVZfqHgKlB9gvIn38/DmL.h4/6n0g4frC8.QcHqHIbMQ0W4Fwv1BK",
    "access" : [ 
        {"id" : ObjectId("58b80a62922a9656b78e86a8"),"role" : "boats"}, 
        {"id" : ObjectId("580df78d3543ce1d905ffb11"),"role" : "accounts"}, 
        {"id" : ObjectId("563160bb671f0c130e6f09b5"),"role" : "accounts"}, 
        {"id" : ObjectId("58e35fea31d05f0e95e0c8fd"),"role" : "crews"}
    ],
    "admins" : [ "test1798@mailinator.com", "test179@mailinator.com", "xyz1793@mailinator.com", "xyz189@mailinator.com"]
}

船只收藏

{
    "_id" : ObjectId("58b80a62922a9656b78e86a8"),
    "name" : "brgvk",
    "email" : "bhargavksdn@gmail.com",
    "path" : "",
    "photo" : "",
    "accounts" : [ ObjectId("58b80a5f922a9656b78e86a7"), ObjectId("580df78d3543ce1d905ffb11")],
    "account_id" : "58b80a5f922a9656b78e86a7"
}

船员集合示例

{
    "_id" : ObjectId("58e35fea31d05f0e95e0c8fd"),
    "firstName" : "brgv",
    "lastName" : "k",
    "phone" : "",
    "email" : "bhargavksdn@gmail.com",
    "bio" : "",
    "photo" : "",
    "path" : "",
    "boats" : [],
    "accounts" : [ ObjectId("563160bb671f0c130e6f09b5"), ObjectId("58b80a5f922a9656b78e86a7")]
}

帐户集合使用 ID 580df78d3543ce1d905ffb11

{
    "_id" : ObjectId("580df78d3543ce1d905ffb11"),
    "profile" : {
        "accountName" : "Nightquest",
        "firstName" : "Jhon",
        "lastName" : "Smith",
        "phone" : "32122333333333",
         photo:"123.jpg",
         path:"1/23"
         "address" : "Melbourne"
    },
    "settings" : {
        color1:"red",
        color2:"blue"
    }
}

帐号集合,ID为563160bb671f0c130e6f09b5

{
    "_id" : ObjectId("563160bb671f0c130e6f09b5"),
    "profile" : {
        "accountName" : "Testing 123",
        "firstName" : "Tom",
        "lastName" : "Kru",
        photo:"123.jpg",
         path:"1/23"
        "phone" : "04181459",
        "address" : "Melbourne"
    },
     "settings" : {
        color1:"green",
        color2:"yellow"
    }
}

现在我正在使用以下聚合管道,并且可以查询数据

db.users.aggregate(
    // Pipeline
    [
        {
            $unwind: { "path": "$access" }
        },
        {
            $project: { "roleId": "$access.id", "email": "$email" }
        },
        {
            $lookup: {
                    "from" :"accounts",
                    "localField": "roleId",
                    "foreignField": "_id",
                    "as": "accounts"
            }
        },
        {
            $lookup: {
                    "from" :"crews",
                    "localField": "roleId",
                    "foreignField": "_id",
                    "as": "crews"
            }
        },
        {
            $lookup: {
                    "from" :"boats",
                    "localField": "roleId",
                    "foreignField": "_id",
                    "as": "boats"
            }
        },
        {
            $unwind: { 
              "path": "$boats",
              "preserveNullAndEmptyArrays": true
             }
        },
        {
            $unwind: { 
              "path": "$crews",
              "preserveNullAndEmptyArrays": true
             }
        },
        {
            $unwind: { 
              "path": "$accounts",
              "preserveNullAndEmptyArrays": true
             }
        },
        {
            $group: { "_id": "$_id", 
               "email" : { 
                 "$first": "$email"
               }, 
               "accounts": { 
                    "$addToSet" : { 
                                 roleId:"$accounts._id",
                                 name:"$accounts.profile.accountName",
                                 "role":{$literal: 'accounts'} ,
                                 path:"$accounts.profile.path",
                                 photo:"$accounts.profile.photo"
                                 } 
               }, 
               "boats": {  

                               "$addToSet" : { 
                                 roleId:"$boats._id",
                                 name:"$boats.name",
                                 "role":{$literal: 'boats'} ,
                                 path:"$boats.path",
                                 photo:"$boats.photo"
                                 } 
               },
               "crews": {  
                  "$addToSet" : { 
                                 roleId:"$crews._id",
                                 name:{ "$concat": [ "$crews.firstName", "$crews.lastName" ] }
                                 "role":{$literal: 'crews'} ,
                                 path:"$crews.path",
                                 photo:"$crews.photo"
                                 } 
               } 
            },


        },
        {
            "$project":{
                "_id": 1,
                 "email": 1,
                 "access": { "$setUnion": [ "$accounts", "$boats", "$crews" ]  }
              }
        }


    ]
)    

虽然查询有效,但它会将空字段插入到访问属性的数组中

[ 
    {
        "roleId" : ObjectId("58e35fea31d05f0e95e0c8fd"),
        "name" : "brgv k",
        "role" : "crews",
        "path" : "",
        "photo" : ""
    }, 
    {
        "role" : "boats"
    }, 
    {
        "name" : null,
        "role" : "crews"
    }, 
    {
        "role" : "accounts"
    }, 
    {
        "roleId" : ObjectId("580df78d3543ce1d905ffb11"),
        "name" : "Nightquest",
        "role" : "accounts"
    }, 
    {
        "roleId" : ObjectId("58b80a62922a9656b78e86a8"),
        "name" : "brgvk",
        "role" : "boats",
        "path" : "",
        "photo" : ""
    }, 
]

我想删除没有roleId 关联的对象。

【问题讨论】:

  • 在 each$lookup 管道之后,您可以放置​​一个 $match 管道来过滤空数组,例如 { "$match": { "accounts": { "$ne": [] } } }
  • 你为什么将preserveNullAndEmptyArrays设置为true?
  • 感谢 chridam 提供过滤器的想法。在您回复后,我得到了工作查询。我在下面发布,如果我们可以进一步简化或编​​写干净的查询,请分享您的想法。

标签: mongodb collections mongodb-query aggregation-framework lookup


【解决方案1】:

db.users.aggregate(

// Pipeline
[
    // Stage 1
    {
        $match: {
            "email": "bhargavksdn@gmail.com"
        }
    },

    // Stage 2
    {
        $unwind: { "path": "$access" }
    },

    // Stage 3
    {
        $project: { "roleId": "$access.id", "role": "$access.role", "email": "$email" }
    },

    // Stage 4
    {
        $lookup: {
                "from" :"accounts",
                "localField": "roleId",
                "foreignField": "_id",
                "as": "accounts"
        }
    },



    // Stage 5
    {
        $lookup: {
                "from" :"crews",
                "localField": "roleId",
                "foreignField": "_id",
                "as": "crews"
        }
    },

    // Stage 6
    {
        $lookup: {
                "from" :"boats",
                "localField": "roleId",
                "foreignField": "_id",
                "as": "boats"
        }
    },

    // Stage 7
    {
        $unwind: { 
          "path": "$boats",
          "preserveNullAndEmptyArrays": true
         }
    },
    {
        $unwind: { 
          "path": "$crews",
          "preserveNullAndEmptyArrays": true
         }
    },
    {
        $unwind: { 
          "path": "$accounts",
          "preserveNullAndEmptyArrays": true
         }
    },

    // Stage 11
    // Stage 11
    {
        $group: { "_id": "$_id", 
           "email" : { 
             "$first": "$email"
           }, 

           "accounts": { 


                "$addToSet" : { 
                             roleId:"$accounts._id",
                             name:"$accounts.profile.accountName",
                              "role":{"$cond": { "if": { "$eq": [ "$role", "accounts" ] }, 
                                        "then": "accounts","else": null}},
                             path:"$accounts.profile.path",
                             photo:"$accounts.profile.photo"
                             } 
           }, 
           "boats": {  


                           "$addToSet" : { 
                             roleId:"$boats._id",
                             name:"$boats.name",
                             "role":{"$cond": { "if": { "$eq": [ "$role", "boats" ] }, 
                                        "then": "boats","else": null}},
                             path:"$boats.path",
                             photo:"$boats.photo"
                             } 
           },
           "crews": {  

              "$addToSet" : { 
                             roleId:"$crews._id",
                             name:{ "$concat": [ "$crews.firstName"," ", "$crews.lastName" ] },
                             "role":{"$cond": { "if": { "$eq": [ "$role", "crews" ] }, 
                                        "then": "crews","else": null}},
                             path:"$crews.path",
                             photo:"$crews.photo"
                             } 
           } 
        },
    },        
            {
                "$project":{
                    "_id": 1,
                     "email": 1,
                     "access": { "$setUnion": ["$accounts", "$boats", "$crews" ]  }
                  }
            },

            { 
                "$project": {
                      "_id": 1,
                    "email": 1,
                    access: {
                        $filter: {
                           input: "$access",
                           as: "item",
                             cond: { $ne: [ "$$item.role", null ] }
                        }
                     }
          }
             }
]

);

【讨论】:

    猜你喜欢
    • 2021-12-07
    • 2022-08-16
    • 2021-05-27
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2021-05-02
    • 1970-01-01
    相关资源
    最近更新 更多