Home > Back-end >  How to chain multiple updateMany() requests to MongoDB (and wait for each response to come back befo
How to chain multiple updateMany() requests to MongoDB (and wait for each response to come back befo

Time:01-23

I am trying to make 3 different updateMany requests inside a get request, each with a different query. They all work except that my third updateMany request only achieves the desired behaviour after the page reloads/refreshes two times.

Here is my code:

app.get('/', (req, res) => {
         let todaysDate = new Date().toString().split(' ').slice(0, 4).join(' ')
         let todaysDateMs = new Date(todaysDate   ', 00:00:00').getTime()

         habitsCollection.updateMany({}, {
            $set: {
               todaysDate,
               todaysDateMs
            }
         }).then(res => {
            habitsCollection.updateMany({ lastClicked: { $ne: todaysDate } }, {
               $set: {
                  clicked: 'false'
               }
            }).then(res => {
               habitsCollection.updateMany({ $expr: { $gte: [{ $subtract: ["$todaysDateMs", "$lastClickedMs"] }, 172800000] } }, {
                  $set: {
                     streak: 0
                  },
               })
            })
         })

         habitsCollection.find({}).toArray()
            .then(results => {
               console.log(results)
               let filtered = results.filter(result => result.clicked === 'false')
               habitsLeft = filtered.length
               res.render('index.ejs', { habits: results, dayVar: 'days', habitsLeft })
            })
      })

I am expecting that on each page load, if a document has a lastClickedMs key/value subtract todaysDateMs key/value and is greater than or equal to 172800000, that the streak value will be reset to 0. This does happen but only after the page has loaded twice.

CodePudding user response:

I think the problem is that you are not waiting for the promises to resolve before you call habitsCollection.find({}).toArray(). You can use Promise.all to handle multiple promises.

app.get('/', (req, res) => {
  let todaysDate = new Date().toString().split(' ').slice(0, 4).join(' ');
  let todaysDateMs = new Date(todaysDate   ', 00:00:00').getTime();

  Promise.all([
    habitsCollection.updateMany({}, {
      $set: {
        todaysDate,
        todaysDateMs
      }
    }),
    habitsCollection.updateMany({ lastClicked: { $ne: todaysDate } }, {
      $set: {
        clicked: 'false'
      }
    }),
    habitsCollection.updateMany({ $expr: { $gte: [{ $subtract: ["$todaysDateMs", "$lastClickedMs"] }, 172800000] } }, {
      $set: {
        streak: 0
      },
    })
  ]).then(() => {
    habitsCollection.find({}).toArray()
      .then(results => {
        console.log(results);
        let filtered = results.filter(result => result.clicked === 'false');
        habitsLeft = filtered.length;
        res.render('index.ejs', { habits: results, dayVar: 'days', habitsLeft });
      });
  });
});
  • Related