Bill
Bill

Reputation: 357

Possible to exclude nested fields in MongoDB with a wildcard?

Suppose I have a document:

{
   "_id": "123",
   "fruit": {
     "apple": {
       "species": "Malus pumila",
       "taste": "Not bad"
     },
     "orange": {
       "species": "Citrus sinensis",
       "taste": "Pretty good"
     }
   }
}

I would like to do something along the lines of db.food.find({}, {"fruit.*.taste": 0}) to not include the taste field in the query results:

{
   "_id": "123",
   "fruit": {
     "apple": {
       "species": "Malus pumila"
     },
     "orange": {
       "species": "Citrus sinensis"
     }
   }
}

Is such a thing possible either through a traditional query or the aggregation pipeline?

Upvotes: 3

Views: 3348

Answers (1)

Kevin Smith
Kevin Smith

Reputation: 14476

There currently isnt a way to exclude on a wildcard on the subdocument. however, you could use the aggregation pipeline with a few $project pipelines and the $objectToArray and $arrayToObject operators to achive the same result:

db.test.aggregate([
    { $project: { "fruit" : { $objectToArray: "$fruit" } } },
    { $project: { "fruit.v.taste" : 0} },
    { $project: { "fruit" : { $arrayToObject: "$fruit"} } }
]);
{
        "_id" : "123",
        "fruit" : {
                "apple" : {
                        "species" : "Malus pumila"
                },
                "orange" : {
                        "species" : "Citrus sinensis"
                }
        }
}

The first $project { "fruit" : { $objectToArray: "$fruit" } } converts the fruit document to a key/value array:

{
        "_id" : "123",
        "fruit" : [
                {
                        "k" : "apple",
                        "v" : {
                                "species" : "Malus pumila",
                                "taste" : "Not bad"
                        }
                },
                {
                        "k" : "orange",
                        "v" : {
                                "species" : "Citrus sinensis",
                                "taste" : "Pretty good"
                        }
                }
        ]
}

Once we've got it in an array format we can just exclude the taste field with a standard projection excluding the field { $project: { "fruit.v.taste" : 0} }:

{
        "_id" : "123",
        "fruit" : [
                {
                        "k" : "apple",
                        "v" : {
                                "species" : "Malus pumila"
                        }
                },
                {
                        "k" : "orange",
                        "v" : {
                                "species" : "Citrus sinensis"
                        }
                }
        ]
}

Then we can just build back up the document using the $arrayToObject operator.

More info can be found here: $arrayToObject - https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/ $objectToArray - https://docs.mongodb.com/manual/reference/operator/aggregation/objectToArray/

Upvotes: 4

Related Questions