U kunt de $cond
operator in een $project stage om de lege attr . te vervangen array met een die een tijdelijke aanduiding bevat zoals null die kan worden gebruikt als een markering om aan te geven dat dit document geen attr . bevat elementen.
Dus je zou een extra $project . invoegen podium zoals dit vlak voor de $unwind :
{
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
Het enige voorbehoud is dat je eindigt met een null waarde in de laatste attrs array voor die groepen die ten minste één document bevatten zonder attrs elementen, dus je moet die client-side negeren.
Voorbeeld
Het voorbeeld gebruikt een gewijzigde $match omdat die in uw voorbeeld niet geldig is.
Documenten invoeren
[
{_id: {type: 1, id: 2}, attrs: []},
{_id: {type: 2, id: 1}, attrs: []},
{_id: {type: 2, id: 2}, attrs: [{name: 'john', type: 22}, {name: 'bob', type: 44}]}
]
Uitvoer
{
"result" : [
{
"_id" : 1,
"attrs" : [
null
]
},
{
"_id" : 2,
"attrs" : [
{
"name" : "bob",
"type" : 44
},
{
"name" : "john",
"type" : 22
},
null
]
}
],
"ok" : 1
}
Geaggregeerde opdracht
db.test.aggregate([
{
$match: {
'_id.servicePath': {
$in: [
null
]
}
}
},
{
$project: {
_id: 1,
"attrs.name": 1,
"attrs.type": 1
}
},
{
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
{
$unwind: "$attrs"
},
{
$group: {
_id: "$_id.type",
attrs: {
$addToSet: "$attrs"
}
}
},
{
$sort: {
_id: 1
}
}
])