Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do inner joining in MongoDB?

Is it possible to do SQL inner joins kind of stuff in MongoDB?

I know there is the $lookup attribute in an aggregation pipeline and it is equivalent to outer joins in SQL, but I want to do something similar to inner joins.

I have three collections which need to merge together:

// User Collection
db.User.find({});

// Output:
{
   ID : 1,
   USER_NAME : "John",
   password : "pass"
}
{

   ID : 2,
   USER_NAME : "Andrew",
   PASSWORD : "andrew"
}

// Role Collection
db.ROLE.find({});

// Output:
{
   ID : 1,
   ROLE_NAME : "admin"
},
{
    ID : 2,
    ROLE_NAME : "staff"
}

// USER_ROLE Collection
db.USER_ROLE.find({});

// Output:
{
   ID : 1,
   USER_ID : 1,
   ROLE_ID : 1
}

I have the above collections and I want to extract only the documents matched with users and their respective roles, not all the documents. How can I manage it in MongoDB?

like image 510
Asantha Thilina Avatar asked Jun 01 '16 17:06

Asantha Thilina


People also ask

Can you do joins in MongoDB?

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

How do I join two documents in MongoDB?

For performing MongoDB Join two collections, you must use the $lookup operator. It is defined as a stage that executes a left outer join with another collection and aids in filtering data from joined documents. For example, if a user requires all grades from all students, then the below query can be written: Students.

Can we join two collections in MongoDB?

Hi, Yes, you can join 2 collections with Aggregation Framework and $unionWith stage. Here are the docs with syntax and examples, so you can check how to do it.


2 Answers

As Tiramisu wrote this looks like schema issue.

You can make a manual inner join, by removing documents where $lookup returned empty array.

....
{$lookup... as myArray},
{$match: {"myArray":{$ne:[]}}},
{$lookup... as myArray2},
{$match: {"myArray2":{$ne:[]}}},

schema change

I personally will go for schema update, like this:

db.User.find({})
{
   ID : 1,
   USER_NAME : "John",
   password : "pass"
   roles:[{ID : 1,  ROLE_NAME : "admin"}]
}


db.ROLE.find({})
{
   ID : 1,
   ROLE_NAME : "admin"
},
like image 43
profesor79 Avatar answered Sep 19 '22 06:09

profesor79


I found answer my self it was

$unwind done the trick to me following query worked for me

    db.USER.aggregate([{
            $lookup: {
                from: "USER_ROLE",
                localField: "ID",
                foreignField: "USER_ID",
                as: "userRole"
            }
        }, {
            $unwind: {
                path: "$userRole",
                preserveNullAndEmptyArrays: false
            }
        }, {
            $lookup: {
                from: "ROLE",
                localField: "userRole.ROLE_ID",
                foreignField: "ID",
                as: "role"
            }
        }, {
            $unwind: {
                path: "$role",
                preserveNullAndEmptyArrays: false
            }
        }, {
            $match: {
                "role.ROLE_NAME": "staff"
            }, {
                $project: {
                    USER_NAME: 1,
                    _id: 0
                }
            }
            ]).pretty()

Anyway thanks for the answers

like image 128
Asantha Thilina Avatar answered Sep 17 '22 06:09

Asantha Thilina