I have a user document like:
{
_id: "s0m3Id",
_skills: ["skill1", "skill2"],
}
Now I want to unwind this document by the _skills
field and add a score for each skill. So my aggregate looks like:
{
'$unwind': {'path': '$_skills', 'preserveNullAndEmptyArrays': true},
},
{
'$project': {
'_skills':
'label': '$_skills',
'skill_score': 1
},
}
},
Sometimes the _skills
field can be empty, however in this case I still want the user document to flow through the aggregation - hence the preserveNullAndEmptyArrays
parameter. However, the problem I'm having is that it will project a skill_score
(though with no label
) onto documents which had empty _skills
array fields. Thus, when I go to $group
the documents later on, those documents now have a non-empty _skills
array, containing a single object, namely {skill_score: 1}
. This is not what I want - I want documents which had empty (or non-existent) _skills
fields to not have any skill_score projected onto them.
So how can I conditionally project a field based on the existence of another field? Using $exists
does not help, because that is intended for querying, not for boolean expressions.
You can use $and with aggregation but you don't have to write it, and is implicit using different filters, in fact you can pipe those filters in case one of them needs a different solution.
Click on the play button under Stage Output to execute just this stage. Or execute the entire pipeline by clicking on the play button in the toolbar. The pipeline and stage outputs should now only show the fields we want. To view the aggregation query’s in mongo shell code, click on Query Code and choose mongo shell from the dropdown.
MongoDB also provides $addFields to add new fields to the documents. To add a new field or to reset the value of an existing field, specify the field name and set its value to some expression. For more information on expressions, see Expressions.
I’ve introduced the MongoDB aggregation pipeline and demonstrated with examples how to use only some stages. The more that you use MongoDB, the more important the aggregation pipeline becomes in allowing you to do all those reporting, transforming, and advanced querying tasks that are so integral to the work of a database developer.
We can paste this whole MongoDB aggregate query and all its stages straight into the Aggregation Editor in Studio 3T. It is pasted in by copying it and clicking on the code paste button as shown. Read more about the Aggregation Editor, Studio 3T’s stage-by-stage MongoDB aggregation query builder.
Updated
This aggregation will set the value of skill_score
to 0
if _skills
does not exist, then use $redact
to remove the subdocument having skill_score
equals to 0
:
db.project_if.aggregate([
{
$unwind: {
path: '$_skills',
preserveNullAndEmptyArrays: true,
}
},
{
$project: {
_skills: {
label: '$_skills',
skill_score: {
$cond: {
if: {
$eq: ['$_skills', undefined]
},
then: 0,
else: 1,
}
}
}
}
},
{
$redact: {
$cond: {
if: { $eq: [ "$skill_score", 0 ] },
then: '$$PRUNE',
else: '$$DESCEND'
}
}
}
]);
Result would be like:
[
{ "_id" : '', "_skills" : { "label" : "skill1", "skill_score" : 1 } },
{ "_id" : '', "_skills" : { "label" : "skill2", "skill_score" : 1 } },
{ "_id" : '' },
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With