您希望在聚合管道中使用 $switch 语句:
db.collection.aggregate([
{ "$group": {
"_id": {
"$let": {
"vars": {
"length": {
"$cond": {
"if": { "$isArray": "$ARRAY_NODE" },
"then": { "$size": "$ARRAY_NODE" },
"else": 0
}
}
},
"in": {
"$switch": {
"branches": [
{ "case": { "$lt": [ "$$length", 50 ] }, "then": "< 50" },
{ "case": { "$lt": [ "$$length", 100 ] }, "then": ">= 50 < 100" },
{ "case": { "$lt": [ "$$length", 150 ] }, "then": ">= 100 < 150" },
{ "case": { "$lt": [ "$$length", 200 ] }, "then": ">= 150 < 200" },
],
"default": "> 200"
}
}
}
},
"count": { "$sum": 1 }
}}
])
如图所示,我们通过在$let 中首先声明来缩短语法,以便为每个计数获取数组的$size。
有一个$bucket 聚合管道阶段基本上是创建类似语句的“快捷方式”,但它的用法是“方便”,因此它的输出并不完全相同:
db.collection.aggregate([
{ "$bucket": {
"groupBy": {
"$cond": {
"if": { "$isArray": "$ARRAY_NODE" },
"then": { "$size": "$ARRAY_NODE" },
"else": 0
}
},
"boundaries": [0, 49, 99, 149, 199],
"default": "> 200"
}}
])
如果您确实需要完整的标签,请使用带有$switch 的完整表单。另请注意,“范围”当然也是一种便利功能,因此遵循它们自己的严格逻辑。当您的逻辑不同时,最好还是写完整的$switch。
还要注意,如果文档中实际上没有这样的字段,则需要在早期版本中使用$isArray 或$ifNull(如下所示),以便进行逻辑测试以返回默认值0 表示“长度”。否则 $size 运算符,它期望一个数组将产生错误:
$size 的参数必须是数组,但类型为:EOO
逻辑处理或返回一个空数组到$size,如The argument to $size must be an Array, but was of type: EOO的答案所示:
这总是并且仍然可以使用$cond 运算符,但只是作为“三元”运算符的语法是嵌套的,而不是$switch 的简洁形式
db.collection.aggregate([
{ "$group": {
"_id": {
"$let": {
"vars": {
"length": {
"$cond": {
"if": { "$ifNull": [ "$ARRAY_NODE", false ] },
"then": { "$size": "$ARRAY_NODE" },
"else": 0
}
}
},
"in": {
"$cond": {
"if": { "$lt": [ "$$length", 50 ] },
"then": "< 50",
"else": {
"$cond": {
"if": { "$lt": [ "$$length", 100 ] },
"then": "> 50 < 100",
"else": {
"$cond": {
"if": { "$lt": [ "$$length", 150 ] },
"then": ">100 < 150",
"else": {
"$cond": {
"if": { "$lt": [ "$$length", 200 ] },
"then": "> 150 < 200",
"else": "> 200"
}
}
}
}
}
}
}
}
}
}
}
])
作为演示。将一些文档插入到具有不同数组大小的集合中:
// Insert documents with arrays of given lengths
db.collection.insertMany(
[
5,40, // < 50 count 2
70, // >= 50 < 100 count 1
120,130, // >= 100 < 150 count 2
170, // >= 150 < 200 count 1
210 // > 200 count 1
].map( n =>
({ "ARRAY_NODE": Array.apply(null,Array(n)).map(() => ({})) }) )
)
然后运行任何聚合语句以产生结果:
{ "_id" : "< 50", "count" : 2 }
{ "_id" : ">= 50 < 100", "count" : 1 }
{ "_id" : ">= 100 < 150", "count" : 2 }
{ "_id" : ">= 150 < 200", "count" : 1 }
{ "_id" : "> 200", "count" : 1 }