我们有一个MongoDB collection像这样:
{
a : string, nullable
b : string, nullable
c : boolean, not nullable
d : string, nullable
e : number, nullable
}
我们需要这样的结果:
{
ab : {
a: <count of a where a is not blank or null>,
b: <count of b where b is not blank or null>
},
c : {
true: <count of c where c true>,
false: <count of c where c false>
},
d : [<all distinct/unique values of d],
e : {
average : <average value of e>,
min : <minimum value of e>,
max : <maximum value of e>
}
}
我们不希望触发多个
find
查询并在内存中处理结果以显示结果。
我们如何仅使用MongoDB的查询来实现这一目标?任何建议将不胜感激
答案 0 :(得分:1)
您需要运行多个管道,然后合并结果。使用$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
。