So, Basically I'm trying to implement a query which is easy in functional programming languages, but I can't seem to make it work in a Mongo Query.
The "statistical" term I found to this is "Max Hold": https://chiptools.readthedocs.io/en/latest/max_hold.html
- I have tried using a mongo aggregation query and use $function, but it seems to be valid only for
map-reduce
kind of calculations (can't find how to keep intermediate values within the documents I'm passing on)
input:
[
{ "key": 1, "value": 10 } ,
{ "key": 2, "value": 11 } ,
{ "key": 3, "value": 9 } ,
{ "key": 4, "value": 12 }
]
output:
[
{ "key": 1, "value": 10, "prefix_max_val": 10 } ,
{ "key": 2, "value": 11, "prefix_max_val": 11 } ,
{ "key": 3, "value": 9, "prefix_max_val": 11 } ,
{ "key": 4, "value": 12, "prefix_max_val": 12 }
]
In Javascript
(or any other general-purpose programming language) I would do something like this (which is a linear time algorithm):
function(input) {
let result = [];
let curr_max = 0;
for (let i=0; i<input.length; i ) {
result[i] = Math.max(curr_max, input[i]);
curr_max = result[i];
}
return result;
}
Thanks :)
EDIT:
- I'm using Mongo0.39
CodePudding user response:
With MongoDB 5.0 you can use setWindowFields
db.collection.aggregate([
{
$setWindowFields: {
sortBy: { key: 1 },
output: {
prefix_max_val: {
$max: "$value",
window: { documents: ['unbounded', 'current'] }
}
}
}
}
])
If you not run MongoDB version 5.0 yet, then try this one:
db.collection.aggregate([
{ $sort: { key: 1 } },
{ $group: { _id: null, data: { $push: "$$ROOT" } } },
{
$set: {
data: {
$reduce: {
input: { $range: [0, { $size: "$data" }] },
initialValue: [],
in: {
$concatArrays: ["$$value", [
{
$mergeObjects: [
{ prefix_max_val: { $max: { $slice: ["$data.value", { $add: ["$$this", 1] }] } } },
{ $arrayElemAt: ["$data", "$$this"] }]
}]
]
}
}
}
}
},
{ $unwind: "$data" },
{ $replaceWith: "$data" }
])
CodePudding user response:
To find the max value you can use the following code:-
db.collection.aggregate({ $group : { _id: null, prefix_max_val: { $max : "$value" }}});