Reputation: 140
extending this following question: MongoDB filter multi sub-documents which I want to filter a document to show only active subdocuments: active cars and active fruits.
Using the aggregation pipeline build by chridam in the following document, where all fruits
are disabled
{
"name":"Andre",
"fruits":[
{
"active":false,
"fruitname":"apple"
},{
"active":false,
"fruitname":"banana"
}
],
"cars":[
{
"active":false,
"carname":"ford"
},{
"active":true,
"carname":"GM"
},
]
}
aggregation pipeline used:
var pipeline = [
{
"$match": {
"name": "Andre",
"fruits.active": true,
"cars.active": true
}
},
{ "$unwind": "$fruits" },
{ "$unwind": "$cars" },
{
"$match": {
"fruits.active": true,
"cars.active": true
}
},
{
"$group": {
"_id": {
"_id": "$_id",
"name": "$name"
},
"cars": { "$addToSet" : "$cars" },
"fruits": { "$addToSet" : "$fruits" }
}
},
{
"$project": {
"_id": 0,
"name": "$_id.name",
"cars": 1,
"fruits": 1
}
}
]
m_object.aggregate(pipeline)
.exec(function (err, result) {
if (err) {
console.log(err);
return;
}
console.log('result');
});
instead of getting
[{
"name":"Andre",
"fruits":[],
"cars":[
{
"active":true,
"carname":"GM"
},
]
}]
aggregation returns
[]
Upvotes: 1
Views: 1034
Reputation: 103345
Try the following aggregation pipeline, it doesn't return an empty array for the inactive elements but is closer to the result:
db.collection.aggregate([
{
"$match": {
"name": "Andre",
"$or": [
{ "fruits.active": true },
{ "cars.active": true }
]
}
},
{ "$unwind": "$fruits" },
{ "$unwind": "$cars" },
{
"$match": {
"$or": [
{ "fruits.active": true },
{ "cars.active": true }
]
}
},
{
"$project": {
"name": 1,
"active_cars": "$cars.active",
"active_fruits": "$fruits.active",
"cars": 1,
"fruits": 1
}
},
{
"$project": {
"name": 1,
"cars": {
"$cond": [
{ "$eq": ["$active_cars", true] },
"$cars",
{}
]
},
"fruits": {
"$cond": [
{ "$eq": ["$active_fruits", true] },
"$fruits",
{}
]
}
}
},
{
"$group": {
"_id": {
"_id": "$_id",
"name": "$name"
},
"cars": { "$addToSet" : "$cars" },
"fruits": { "$addToSet" : "$fruits" }
}
},
{
"$project": {
"_id": 0,
"name": "$_id.name",
"cars": 1,
"fruits": 1
}
}
])
Output
/* 1 */
{
"result" : [
{
"cars" : [
{
"active" : true,
"carname" : "GM"
}
],
"fruits" : [{}],
"name" : "Andre"
}
],
"ok" : 1
}
Upvotes: 1
Reputation: 46291
Let's look at the very first operation, the query criteria, in the pipeline:
"$match": {
"name": "Andre",
"fruits.active": true,
"cars.active": true
}
In English: "find me all documents with name = Andre
where there is at least one active fruit and at least one active car."
So you're explicitly requesting not to get any results where there are no active fruits and cars, hence the result is empty.
Upvotes: 1