Search code examples
javascriptmongodbmongoosenodesfindoneandupdate

Mongodb findOneAndUpdate() compare sums of date and timestamps


I'm working on a MongoDB (+mongoose) based scheduler where tasks have the following type

TaskSchema {
  running: Boolean
  executedAt: Date,
  next: Number (millisecond)
}

I wish to fetch Tasks which should be executed meaning the sum of executedAt + next < now Since the scheduler should lock the Task, the running flag should be flipped to true in the same operation, hence I'm using findOneAndUpdate() I'm stuck at dealing with the sum of executedAt and next. How would one compare the sum of these to new Date/Date.now() ?

When doing an aggregation one could use $dateAdd from what I understand so in a find query could be something. like the following:

    Task.find({
      $and: [
        { running: { $ne: null } },
        { running: false },
        { next: { $ne: null } },
        { executedAt: { $ne: null } },
        {
          $expr: {
            $lt: [
              {
                $dateAdd: {
                  startDate: '$executedAt',
                  unit: 'millisecond',
                  amount: '$next',
                },
              },
              new Date().toUTCString(),
            ],
          },
        },
      ],
    })

However this does not work.


Solution

  • Apparently, my initial attempt works and the above query is nearly correct. Since I didn't set the $addDate timezone explicitly I tried making the new Date() a UTC string. Considering @Wernfrieds comment this complies to my requirements:

    Task.find({
      $and: [
        { running: { $ne: null } },
        { running: false },
        { next: { $ne: null } },
        { executedAt: { $ne: null } },
        {
          $expr: {
            $lt: [
              {
                $dateAdd: {
                  startDate: '$executedAt',
                  unit: 'millisecond',
                  amount: '$next',
                },
              },
              new Date(),
            ],
          },
        },
      ],
    })