Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to join multiple collections with $lookup in mongodb

I want to join more than two collections in MongoDB using the aggregate $lookup. Is it possible to join? Give me some examples.

Here I have three collections:

users:

{         "_id" : ObjectId("5684f3c454b1fd6926c324fd"),     "email" : "[email protected]",     "userId" : "AD",     "userName" : "admin" } 

userinfo:

{     "_id" : ObjectId("56d82612b63f1c31cf906003"),     "userId" : "AD",     "phone" : "0000000000" } 

userrole:

{     "_id" : ObjectId("56d82612b63f1c31cf906003"),     "userId" : "AD",     "role" : "admin" } 
like image 476
Siva M Avatar asked Mar 05 '16 12:03

Siva M


People also ask

Can MongoDB query joins between collections?

Fortunately, MongoDB Joins can be performed in MongoDB 3.2 as it introduces a new Lookup operation that can perform Join operations on Collections.

Can a MongoDB have multiple collections?

As mentioned above, a single database can have multiple collections.

What is $lookup in MongoDB?

$lookup performs an equality match on the localField to the foreignField from the documents of the from collection. If an input document does not contain the localField , the $lookup treats the field as having a value of null for matching purposes.


2 Answers

The join feature supported by Mongodb 3.2 and later versions. You can use joins by using aggregate query.
You can do it using below example :

db.users.aggregate([      // Join with user_info table     {         $lookup:{             from: "userinfo",       // other table name             localField: "userId",   // name of users table field             foreignField: "userId", // name of userinfo table field             as: "user_info"         // alias for userinfo table         }     },     {   $unwind:"$user_info" },     // $unwind used for getting data in object or for one record only      // Join with user_role table     {         $lookup:{             from: "userrole",              localField: "userId",              foreignField: "userId",             as: "user_role"         }     },     {   $unwind:"$user_role" },      // define some conditions here      {         $match:{             $and:[{"userName" : "admin"}]         }     },      // define which fields are you want to fetch     {            $project:{             _id : 1,             email : 1,             userName : 1,             userPhone : "$user_info.phone",             role : "$user_role.role",         }      } ]); 

This will give result like this:

{     "_id" : ObjectId("5684f3c454b1fd6926c324fd"),     "email" : "[email protected]",     "userName" : "admin",     "userPhone" : "0000000000",     "role" : "admin" } 

Hope this will help you or someone else.

Thanks

like image 200
Amit Kumar Avatar answered Oct 17 '22 00:10

Amit Kumar


You can actually chain multiple $lookup stages. Based on the names of the collections shared by profesor79, you can do this :

db.sivaUserInfo.aggregate([     {         $lookup: {            from: "sivaUserRole",            localField: "userId",            foreignField: "userId",            as: "userRole"         }     },     {         $unwind: "$userRole"     },     {         $lookup: {             from: "sivaUserInfo",             localField: "userId",             foreignField: "userId",             as: "userInfo"         }     },     {         $unwind: "$userInfo"     } ]) 

This will return the following structure :

{     "_id" : ObjectId("56d82612b63f1c31cf906003"),     "userId" : "AD",     "phone" : "0000000000",     "userRole" : {         "_id" : ObjectId("56d82612b63f1c31cf906003"),         "userId" : "AD",         "role" : "admin"     },     "userInfo" : {         "_id" : ObjectId("56d82612b63f1c31cf906003"),         "userId" : "AD",         "phone" : "0000000000"     } } 

Maybe this could be considered an anti-pattern because MongoDB wasn't meant to be relational but it is useful.

like image 29
Derek Avatar answered Oct 16 '22 22:10

Derek