0

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.

5
  • Your query says { $match: { "types.isActive": true } }, but the input document has "tyoes.isActive" values as false. So, no documents get selected. Commented Oct 14, 2019 at 7:16
  • That is the expected behavior. Commented Oct 14, 2019 at 7:24
  • can I do that to return EMPTY array if there are no true records present? Commented Oct 14, 2019 at 7:31
  • 1
    You can check here: stackoverflow.com/questions/3985214/… Commented Oct 14, 2019 at 7:39
  • @Rajath You can. But, not with that query pipeline you are using. Commented Oct 14, 2019 at 7:41

1 Answer 1

1

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
                }
        ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, prasad I implemented it in the same way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.