我有一个集合(我们称之为'AwesomeCollection'),其中包含如下所示的文档:
{
"_id" : "someID",
"DateAdded" : ISODate("2017-06-08T22:35:43.517Z"),
"Info" : {
"size" : NumberLong(32530454),
"filtype" : "APK"
},
"ARRAY_NODE" : [{
"key1" : "val1"
}, {
"key2" : "val2"
}, {
"key3" : "val3"
}]
}
ARRAY_NODE是一个数组字段,可以包含1到200个项目。
我想编写一个查询,返回AwesomeCollection中每个类别的文档数:
答案 0 :(得分:1)
您希望聚合管道中的$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
聚合管道阶段基本上是一个&#34;快捷方式&#34;用于创建类似的声明,但它的使用是方便的&#34;所以输出不完全相同:
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
的完整表单。另请注意&#34;范围&#34;当然也是一种便利功能,因此遵循他们自己严格的逻辑。当你的逻辑不同时,最好再写$switch
。
另请注意,如果文档中实际不存在此类字段,则必须在早期版本中使用$isArray
或$ifNull
(如稍后所示)才能对逻辑进行逻辑测试返回默认值0
以指示&#34;长度&#34;。否则,期望数组的$size
运算符将产生错误:
$ size的参数必须是数组,但类型为:EOO
逻辑处理或将空数组返回$size
,如以下答案所示:The argument to $size must be an Array, but was of type: EOO
使用$cond
运算符始终可以实现这一点,但它的语法只是&#34;三元&#34;运算符是嵌套的,而不是$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 }