I'm doing an aggregation in MongoDB which should have an array fields projection in its $project
stage . But I can't access array fields by their indexes :
{//projection stage
$project: {
'foo' : { '$ifNull' : ['$bar.0.baz.0.qux', '*'] }
}
}
This sets foo
to an empty array . bar is a multidimensional array field. my MongoDB version is 3.2 . What can I do for this without the hassle of $unwind/$group
old heavy solution ?
Thanks for your help .
Use $slice
, $map
and $arrayElemAt
:
{ "$project": {
"foo": {
"$ifNull": [
{ "$arrayElemAt": [
{ "$map": {
"input": { "$slice": [
{ "$map": {
"input": { "$slice": [ "$bar", 0, 1 ] },
"as": "el",
"in": "$$el.baz"
}},
0, 1
]},
"as": "el",
"in": { "$arrayElemAt": [ "$$el.qux", 0 ] }
}},
0
]},
"*"
]
}
}}
So the inner $map
operators allow you to just select the particular fields out of each array, which you can $slice
at the desired position to just return that element. i.e 0,1
is zero index and just one element.
The for the final resulting array you just use $arrayElemAt
and retrieve the indexed element turning it into a single value.
Of course the $ifNull
tests might need to be more involved depending on your structure, as if it's not consistent then you probably need to check each $map
input and swap with a result accordingly.
But the general process is :
$map
to get fields$slice
to reduce arrays from $map
$arrayElemAt
on the final array result.On something like this:
db.foo.insert({
"bar": [
{
"baz": [
{ "qux": 2 },
{ "qux": 5 }
]
},
{
"baz": [
{ "qux": 3 },
{ "qux": 4 }
]
}
]
})
Produces:
{ "_id" : ObjectId("56e8c6b8ff2a05c0da90b31e"), "foo" : 2 }
Use multiple $project stage with $arrayElemAt operator with temporary fields.
{$project:{"tmp": {$arrayElemAt:["$bar",0]}}},
{$project:{"tmp2": {$arrayElemAt:["$tmp.baz",0]}}}
than your value is at $tmp2.qux.
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