TL; DR
是否有mongo数组运算符可以检测数组是否包含至少一个大于前一个的条目?例如
[1,1,1,2,2,2] -> true
[1,1,1,0,0,0] -> false
我们正在使用mongo跟踪网络活动,其中相对字段packets
是一段时间内活动的总和。最好通过示例来说明:
[0,0,0,0] -> no packets
[5,5,5,5] -> 5 packets continuous
[0,0,5,5] -> No packets and then a single event of 5
[0,0,5,10] -> two events, each increasing total packets by 5
我们的目标是识别有活动的记录(即,数据包数量发生变化)。首先,使用$addToSet运算符然后在count> 1处进行设置似乎很简单。EG:
[0,0,0,0] -> [0] -> false
[5,5,5,5] -> [5] -> false
[0,0,5,5] -> [0,5] -> true
[0,0,5,10] -> [0,5,10] -> true
但是,我们随后了解到一个附加约束。当活动变为0时,即被视为重置,因此不应计为活动,例如
[5,5,0,0] -> false (a reset event)
[0,0,5,5] -> true (a network event)
[5,0,5,0] -> true (a reset event followed be a network event followed by a reset - but because there was a network event this is true)
除了为零时,活动总是会增加(例如,[5,5,0,0]
是可能的,但[5,5,4,4]
则不是)。
因此,我们需要确定数据是否包含单个条目,其值大于前一个值。。是否有mongo运算符可以扫描数组并在任何元素大于其前一个元素的情况下返回true?
谢谢
答案 0 :(得分:1)
您可以利用$reduce运算符来扫描数组,并保留先前的值以将其与当前值进行比较。
对于示例数据,例如:
db.col.aggregate([
{
$project: {
result: {
$reduce: {
input: "$data",
initialValue: {
previous: { $arrayElemAt: [ "$data", 0 ] },
decision: false
},
in: {
previous: "$$this",
decision: {
$or: [
"$$value.decision",
{ $gt: [ "$$this", "$$value.previous" ] }
]
}
}
}
}
}
},
{
$project: {
_id: 0,
result: "$result.decision"
}
}
])
您可以运行:
{ "result" : true }
{ "result" : false }
输出:
data.table
答案 1 :(得分:1)
基本上,您正在使用$reduce
进行遍历,使用当前值和先前值并进行比较
db.collection.aggregate([
{ "$addFields": {
"result": {
"$reduce": {
"input": {
"$range": [ 1, { "$size": "$source_array" } ]
},
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$gt": [
{ "$arrayElemAt": [ "$source_array", "$$this" ]},
{ "$arrayElemAt": [
"$source_array",
{ "$subtract": [ "$$this", 1 ] }
]}
]}
]
}
}
}
}}
]);
给出如下数据:
{ "source_array" : [ 0, 0, 0, 0 ], "expect" : false }
{ "source_array" : [ 5, 5, 5, 5 ], "expect" : false }
{ "source_array" : [ 0, 0, 5, 5 ], "expect" : true }
{ "source_array" : [ 5, 5, 0, 0 ], "expect" : false }
{ "source_array" : [ 5, 0, 5, 0 ], "expect" : true }
{ "source_array" : [ 5, 0, 5, 5 ], "expect" : true }
{ "source_array" : [ 5, 5, 4, 4 ], "expect" : false }
返回:
[
{
"source_array": [
0,
0,
0,
0
],
"expect": false,
"result": false
},
{
"source_array": [
5,
5,
5,
5
],
"expect": false,
"result": false
},
{
"source_array": [
0,
0,
5,
5
],
"expect": true,
"result": true
},
{
"source_array": [
5,
5,
0,
0
],
"expect": false,
"result": false
},
{
"source_array": [
5,
0,
5,
0
],
"expect": true,
"result": true
},
{
"source_array": [
5,
0,
5,
5
],
"expect": true,
"result": true
},
{
"source_array": [
5,
5,
4,
4
],
"expect": false,
"result": false
}
]
所有这些都是通过将$arrayElemAt
与数组中的索引值一起使用来完成的。使用$range
从1..length
生成索引,并将n
与n-1
分别作为当前索引和先前索引。
逻辑表明,获得true
结果时无需进一步比较。