Here I have two collections
Category
[
{
id: 1,
name: "MEN",
status: true
},
{
id: 2,
name: "WOMEN",
staus: true
}
]
Service
[
{
name: "service a",
category_id: 1,
status: true
},
{
name: "service b",
category_id: 1,
status: true
},
{
name: "service c",
category_id: 1,
status: true
},
{
name: "service d",
category_id: 1,
status: false
}
]
I want all services in the category wise. for that, I have used lookup
aggression. I have added one more stage in aggression to filter the service with status true.
I have tried with the following.
db.category.aggregate([
{
"$lookup": {
"from": "services",
"localField": "id",
"foreignField": "category_id",
"as": "services"
}
},
{
"$match": {
"services.status": true
}
}
])
Expected Output
[
{
"_id": ObjectId("5a934e000102030405000000"),
"id": 1,
"name": "MEN",
"services": [
{
"_id": ObjectId("5a934e000102030405000002"),
"category_id": 1,
"name": "service a",
"status": true
},
{
"_id": ObjectId("5a934e000102030405000003"),
"category_id": 1,
"name": "service b",
"status": true
},
{
"_id": ObjectId("5a934e000102030405000004"),
"category_id": 1,
"name": "service c",
"status": true
},
],
"status": true
}
]
Have a look at https://mongoplayground.net/p/FXNakB7cLse.
CodePudding user response:
You have multiple options.
With your data you can simply use $filter
in a project stage like this:
db.category.aggregate([
{
"$lookup": {
"from": "services",
"localField": "id",
"foreignField": "category_id",
"as": "services"
}
},
{
"$project": {
"id": 1,
"name": 1,
"status": 1,
"services": {
"$filter": {
"input": "$services",
"as": "s",
"cond": {
"$eq": [
"$$s.status",
true
]
}
}
}
}
}
])
Example here
Other options is to do the $lookup
with the condition:
db.category.aggregate([
{
"$lookup": {
"from": "services",
"let": {
"id": "$id"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
"$eq": [
"$category_id",
"$$id"
]
},
{
"$eq": [
"$status",
true
]
}
]
}
}
}
],
"as": "services"
}
}
])
Example here
And the last option (I don't recommend do in this way) is using $unwind
, $match
and $group
: example here
Also, if you don't want to get the document where services: []
you can add a $match
stage into the first two options:
{
"$match": {
"services": {
"$ne": []
}
}
}