Reputation: 13
In mongo I have a documents that follow the below pattern :
{
name: "test",
codes: [
[
{
code: "abc",
value: 123
},
{
code: "def",
value: 456
},
],
[
{
code: "ghi",
value: 789
},
{
code: "jkl",
value: 012
},
]
]
}
I'm using an aggregate query (because of joins) and in a $project
block I need to return the "name"
and the value of the object that has a code of "def"
if it exists and an empty string if it doesn't.
I can't simply $unwind
codes and $match
because the "def"
code is not guaranteed to be there.
$filter
seems like the right approach as $elemMatch
doesn't work, but its not obvious to me how to do this on nested array of arrays.
Upvotes: 1
Views: 55
Reputation: 17915
You can try below query, instead of unwinds & filter this can give you required result with less docs to operate on :
db.collection.aggregate([
/** merge all arrays inside codes array into code array */
{
$addFields: {
codes: {
$reduce: {
input: '$codes',
initialValue: [],
in: { $concatArrays: ["$$value", "$$this"] }
}
}
}
},
/** project only needed fields & value will be either def value or '',
* if 'def' exists in any doc then we're check index of it to get value of that particular object using arrayElemAt */
{
$project: {
_id:0, name: 1, value:
{
$cond: [{ $in: ["def", '$codes.code'] }, { $arrayElemAt: ['$codes.value', { $indexOfArray: ["$codes.code", 'def'] }] }, '']
}
}
}])
Test : MongoDB-Playground
Upvotes: 1