LeM*_*sel 2 mongodb aggregation-framework
我的MongoDB文档如下所示:
{StatCode : "...", LoadTime : "..."}
Run Code Online (Sandbox Code Playgroud)
例如,数据可能如下所示:
+-----+----------+------------+
| _id | StatCode | LoadTime |
+-----+----------+------------+
| 1 | 200 | 0,345 |
| 2 | 200 | 0,234 |
| 3 | 200 | 0,396 |
| 4 | 200 | 1,234 |
| 5 | 200 | 2,564 |
| 6 | 200 | 0,437 |
| 7 | 301 | 0,523 |
| 8 | 301 | 0,628 |
| 9 | 301 | 0,712 |
| 10 | 200 | 1,784 |
+-----+----------+------------+
Run Code Online (Sandbox Code Playgroud)
我希望通过LoadTime值得到计数组,如下所示:最慢(超过2),慢(1到2之间),中(0到1之间)和快(低于0.5)
使用Data示例,结果如下所示:
+----------+-------+
| Info_id | Count |
+----------+-------+
| Slowest | 1 |
| Slow | 2 |
| Medium | 3 |
| Fast | 4 |
+----------+-------+
Run Code Online (Sandbox Code Playgroud)
编辑:备注Neil Lunn,来自MongoDB的示例文档
{
"_id" : 1,
"LoadTime" : NumberLong(345),
"StatCode" : 200
}
{
"_id" : 2,
"LoadTime" : NumberLong(234),
"StatCode" : 200
}
....
{
"_id" : 9,
"LoadTime" : NumberLong(712),
"StatCode" : 301
}
{
"_id" : 10,
"LoadTime" : NumberLong( 1784),
"StatCode" : 200
}
Run Code Online (Sandbox Code Playgroud)
如何使用MongoDB聚合框架实现此目的?
你想要的是$ cond运算符和$和.的相当多的嵌套条件.但这应该给你你想要的.
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] },
"Slowest", // return "Slowest" where true
{"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow", // then "Slow" here where true
{"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 1000] },
{"$gte": ["$LoadTime", 500 ] }
]},
"Medium", // then "Medium" where true
"Fast" // and finally "Fast" < 500
]}
]}
]},
"count": {"$sum": 1}
}},
{"$sort": { "count": 1 }}
])
Run Code Online (Sandbox Code Playgroud)
由于你的时间是整整几毫秒,你可以看到我要求编辑的原因.
因为$ cond是一个三元运算符,它需要三个参数:
因此,我们的想法是,您将整个条件嵌套,在false上移动到下一个测试,直到找到要匹配的条件,并返回一个值.
的$和部分是一个排列条件包括.这为您提供了范围.所以在最长的部分:
{"$cond": [ // Evaluate here
{"$and": [ // Within the range of the next 2
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow", // true condition - return
{"$cond": [ // false - move to next eval
Run Code Online (Sandbox Code Playgroud)
通过你的级联留下"快速" times500毫秒.
每个都keys被发送到组,我们只是{ $sum: 1 }为了得到一个计数,因为它们被组合在一起.
如果您需要在自己的语言实现中,整个pipeline内容
aggregate(..)
只是JSON,所以你可以将它解析为你的原生数据结构,如果手工翻译让你恍惚,或者像我一样你只是懒惰.
由于评论,似乎有必要解释所提出的查询的形式.所以这里是编辑附录以供澄清.
在学习使用聚合管道时,以及写出和测试复杂的一系列阶段或逻辑的良好实践时,我发现通过一步一步地实现部件来可视化结果是有用的.因此,在写这样的事情我的情况下,第一个步骤是如下:
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] },
"Slowest",
null
]}
}}
])
Run Code Online (Sandbox Code Playgroud)
现在,这将让我的"最慢"为我所期望的计数,然后斗别的一切都成null.所以到目前为止我有一个阶段可以看到结果.但是在测试时,我会在继续构建链之前实际执行类似的操作:
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow",
null
]}
}}
])
Run Code Online (Sandbox Code Playgroud)
所以我只是将"慢"(2000到1000 之间)的结果与null桶中的其他所有内容相比较.所以我的总体数量保持不变.
在最后的查询中,正如所指出的那样,在嵌套的三元条件中,第一阶段已经评估false了下一个运算符正在测试的项目.这意味着它们不 大于第一阶段已经测试过的值,并且不需要测试该条件,因此可以写成如下:
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] }, // Caught everything over 2000
"Slowest",
{"$cond": [
{"$gte": ["$LoadTime", 1000] } // Catch things still over 1000
"Slow",
{"$cond": [ // Things under 1000 go here
// and so on
Run Code Online (Sandbox Code Playgroud)
这短路,因为没有评价真正需要测试的东西,不会通过走到下一个逻辑条件.
因此,纯粹出于视觉原因以及剪切和粘贴逻辑的纯粹懒惰,我们最终使用$和条件来扩展形式来包装范围.但是,对于那些不使用的的使用三元形式有一个清晰的视觉线索,结果在这个阶段被匹配将下降之间的价值观2000ms和1000ms,等等,这是您要在每个范围的结果是什么.
正如我所说的,不必要有因为逻辑是如何工作的,但它是一个发展阶段,并明确对谁尚未人们避开他们头上的的使用三元形式$ COND提供.
| 归档时间: |
|
| 查看次数: |
903 次 |
| 最近记录: |