Andre Torbitoni
Andre Torbitoni

Reputation: 140

mongoDB Aggregation retuns empty

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

Answers (2)

chridam
chridam

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

mnemosyn
mnemosyn

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

Related Questions