Reputation: 165
I've got a mongodb aggregation pipeline with a $project stage and I'd like to include certain fields only if conditions are met. Specifically, I'd like to exclude the _id in one condition and include a second field 'second_id' in the other condition.
I know that it's not possible (yet) to exclude fields from a mongodb $project, but is it possible to conditionally include them?
Is there a way to conditionally exclude the _id field? It accepts a 0 or 1, but what if I want to determine that 0 or 1 based on an if statement. How would this be done?
Pseudocode for _id:
$project: { _id: { $ifNull: [ "$user_id", 0 ] } }
The main use of this would be to use the doc.user_id as the result _id, or allow mongodb to create a new autoincrement _id if that user_id is null.
Upvotes: 6
Views: 5541
Reputation: 6403
Maybe this was not doable when the question was asked, but now it is.
There is a way to conditionally include/exclude a particular field in $project
stage.
This can be achieved using $cond
to evaluate your condition, and then return either '$true'
or '$false'
{
myConditionalField:{$cond:{
if:{
$eq:['$some_field','some_value']
},
then:'$false',
else:'$true'
}}
}
Here, the field myConditionalField
will be projected only if the value of some_field
from previous stage matched some_value
.
NOTE: Its assumed here that myConditionalField
already exists from a previous stage. If it doesn't, then the else
should be $some_field
or whatever field you want to be projected.
Upvotes: 1
Reputation: 36
I have a trick for this one:
"_id": {"$cond": [{"$eq": ["$user_id", null]}, "$nonExistinField", "$user_id"]}
Upvotes: 1
Reputation: 865
There isn't a way currently to do this within the $project stage, but you can use the $redact stage to remove the field conditionally (i.e. you set the value to 0 like you are doing in your example.
db.collection.aggregate(
... matching and stuff ...
{$project: { _id: { $ifNull: [ "$user_id", 0 ] } }},
{$redact: {
{$cond: {
if: { $eq: [ "$user_id", 0 ] },
then: '$$PRUNE',
else: '$$DESCEND'
}}
}
Upvotes: 4