Home > Blockchain >  MongoDB Max-Hold Algorithm
MongoDB Max-Hold Algorithm

Time:02-18

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'] }
            }
         }
      }
   }
])

Mongo Playground

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" }}});
  • Related