The results Mongo collection contains the following documents:
[
{
"id": 1,
"failures": [
{
"level": "BASIC",
"message": "failure",
},
{
"level": "BASIC",
"message": "failure",
},
{
"level": "WARNING",
"message": "failure",
},
],
"rules": ["X", "Y"]
},
{
"id": 2,
"failures": [
{
"level": "BASIC",
"message": "failure",
},
{
"level": "WARNING",
"message": "failure",
}
],
"rules": ["X"]
},
{
"id": 3,
"failures": [],
"rules": ["X", "Y"]
},
]
I would like to create a Mongo query that selects the documents matching the provided IDs, counts the level of each elements of the failures array into a object, and project the rules property. Given the collection above, and when providing as input the IDs [1, 2, 3], this should be the expected output:
[
{
"id": 1,
"counts": {
"BASIC": 2,
"WARNING": 1
}
"rules": ["X", "Y"]
},
{
"id": 2,
"counts": {
"BASIC": 1,
"WARNING": 1
},
"rules": ["X"]
},
{
"id": 3,
"counts": {},
"rules": ["X", "Y"]
},
]
This is the Mongo query I am building:
db.collection.aggregate([
{
$match: {
"id": {
$in: [
1,
2,
3
]
}
}
},
{
$unwind: {
path: "$failures",
preserveNullAndEmptyArrays: true
}
},
{
$group: {
_id: {
id: "$id",
level: "$failures.level"
},
count: {
$sum: 1
},
rules: {
$first: "$rules"
}
}
},
{
$group: {
_id: "$_id.id",
count: {
$push: {
k: "$_id.level",
v: "$count"
}
},
rules: {
$first: "$rules"
}
}
},
{
$project: {
"_id": 0,
"id": "$_id.id",
"count": {
$arrayToObject: "$count"
},
"rules": 1
}
}
])
However, this query fails when applying the $arrayToObject operator with the following error:
$arrayToObject requires an object keys of 'k' and 'v'
This is because documents with no elements in the failures array have no key "k" when pushing the "_id.level" property.
How can I fall back on an empty object if any of these keys are not present?
Thanks in advance.
Your document with
id: 3contains an emptyfailuresarray, if you debug until stage 4th, you will see thecountarray with the document missingkfield.Approach 1
Use the
$condoperator to handle when missing value forfailures.levelin both$groupstages.Demo Approach 1 @ Mongo Playground
Approach 2
Use the
$facetstage to handle thefailuresarray which is empty and non-empty separately.Combine both
emptyFailuresandwithFailuresarrays into one.Deconstruct the
failuresarray.Replace the input document with the
failuresobject.Demo Approach 2 @ Mongo Playground