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?
Fortunately, MongoDB Joins can be performed in MongoDB 3.2 as it introduces a new Lookup operation that can perform Join operations on Collections.
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.
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.
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"
},
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With