Bạn có thể sử dụng $cond
toán tử trong $project giai đoạn để thay thế attr trống mảng với một mảng có chứa trình giữ chỗ như null có thể được sử dụng làm điểm đánh dấu để cho biết rằng tài liệu này không chứa bất kỳ attr nào các phần tử.
Vì vậy, bạn sẽ chèn thêm một $project giai đoạn như thế này ngay trước $unwind :
{
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
Cảnh báo duy nhất là bạn sẽ kết thúc bằng null giá trị trong attrs cuối cùng mảng cho những nhóm chứa ít nhất một tài liệu mà không có bất kỳ attrs , vì vậy bạn cần bỏ qua những yếu tố phía máy khách đó.
Ví dụ
Ví dụ sử dụng $match đã thay đổi vì cái trong ví dụ của bạn không hợp lệ.
Tài liệu đầu vào
[
{_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}]}
]
Đầu ra
{
"result" : [
{
"_id" : 1,
"attrs" : [
null
]
},
{
"_id" : 2,
"attrs" : [
{
"name" : "bob",
"type" : 44
},
{
"name" : "john",
"type" : 22
},
null
]
}
],
"ok" : 1
}
Lệnh tổng hợp
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
}
}
])