Rajath
Rajath

Reputation: 2978

How to return Objects with empty sub Array document if sub Array documents don't satisfy the match condition?

Mongoose is not returning Objects if sub Array documents don't satisfy the match condition in mongoose.

MongoDB Query:

db.fruits.aggregate(        
    { $match: { "isActive": true, fruitId: "kipld" } },
    { $unwind: '$types' },
    { $match: { "types.isActive": true } },
    { $group: {
            _id: '$_id', 
            name: {$first: '$name'}, 
            price: { $first: '$price' },
            types : { $push : '$types' }
        }
    },
    { $project: {
            '_id': 1, 
            'name':1, 
            'price': 1, 
            'types': 1,
        }
    }
)

MongoDB Collection:

{
    _id: "abcdefg",
    fruitId: "kipld",
    isActive: true,
    types :[
        {
            name: "Kashmir Apple",
            price: 90,
            isActive: false
        },
        {
            name: "American Apple",
            price: 120,
            isActive: false
        }
    ]
}

Expected result will be like:

{
    _id: "abcdefg",
    fruitId: "kipld",
    isActive: true,
    types :[]
}

But when I'm running the above query I'm not getting anything.

Upvotes: 0

Views: 257

Answers (1)

prasad_
prasad_

Reputation: 14317

You can get the desired result using the $filter aggregation operator. This just filters all the array elements and returns the array with the matching filter condition. Note the filter is applied to each document's array. So, in your case the $unwind and $group stages are not needed to get the result.

Sample fruits collection:

{
        "_id" : "abcdefg",
        "fruitId" : "kipld",
        "isActive" : true,
        "types" : [
                {
                        "name" : "Kashmir Apple",
                        "price" : 90,
                        "isActive" : false
                },
                {
                        "name" : "American Apple",
                        "price" : 120,
                        "isActive" : false
                }
        ]
}
{
        "_id" : "uvwxyz",
        "fruitId" : "kipld",
        "isActive" : true,
        "types" : [
                {
                        "name" : "Kinnaur Apple",
                        "price" : 80,
                        "isActive" : false
                },
                {
                        "name" : "Shimla Apple",
                        "price" : 70,
                        "isActive" : true
                }
        ]
}

Aggregation Query:

db.fruits.aggregate([
  { $match: { "isActive": true, fruitId: "kipld" } },
  { $project: { _id: 1, fruitId: 1, isActive: 1, 
                result_types: { $filter: {
                                   input: "$types",
                                      as: "type",
                                    cond: { $eq: [ "$$type.isActive", true ] }
                                 } 
                             } } 
   }
])

The Output:

Note the "result_types" empty array where the types.isActive values are false for all elements of "types" array. Only the elements with a value of true are in the result output.

{
        "_id" : "abcdefg",
        "fruitId" : "kipld",
        "isActive" : true,
        "result_types" : [ ]
}
{
        "_id" : "uvwxyz",
        "fruitId" : "kipld",
        "isActive" : true,
        "result_types" : [
                {
                        "name" : "Shimla Apple",
                        "price" : 70,
                        "isActive" : true
                }
        ]
}

Upvotes: 1

Related Questions