Вам нужно запустить несколько конвейеров, а затем объединить результаты. Это возможно с оператором $ facet . Попробуйте запрос ниже:
db.col.aggregate([
{
$facet: {
q1: [
{ $match: { a: { $exists: true, $ne: null } } },
{ $count: "total" }
],
q2: [
{ $match: { b: { $exists: true, $ne: null } } },
{ $count: "total" }
],
q3: [
{ $match: { c: true } },
{ $count: "total" }
],
q4: [
{ $match: { c: false } },
{ $count: "total" }
],
q5: [
{
$group: {
_id: null,
unique: { $addToSet: "$d" }
}
}
],
q6: [
{
$group: {
_id: null,
average: { $avg: "$e" },
min: { $min: "$e" },
max: { $max: "$e" },
}
}
],
}
},
{
$project: {
q1: { $arrayElemAt: [ "$q1", 0 ] },
q2: { $arrayElemAt: [ "$q2", 0 ] },
q3: { $arrayElemAt: [ "$q3", 0 ] },
q4: { $arrayElemAt: [ "$q4", 0 ] },
q5: { $arrayElemAt: [ "$q5", 0 ] },
q6: { $arrayElemAt: [ "$q6", 0 ] }
}
},
{
$project: {
"ab.a": { $ifNull: [ "$q1.total", 0 ] },
"ab.b": { $ifNull: [ "$q2.total", 0 ] },
"c.true": { $ifNull: [ "$q3.total", 0 ] },
"c.false": { $ifNull: [ "$q4.total", 0 ] },
d: "$q5.unique",
"e.average": "$q6.average",
"e.min": "$q6.min",
"e.max": "$q6.max",
}
}
])
То есть q1-q6
- это просто отдельные конвейеры агрегации. Каждый из них возвращает массив результатов, которые можно преобразовать в отдельные вложенные документы, используя $ arrayElemAt . Затем вы можете использовать простой $project
, чтобы преобразовать его в конечный результат. Использование $ addToSet для получения уникальных значений для d
и $ ifNull для замены этих подсчетов, когда значение по умолчанию 0
.
отсутствует.