Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update query adding ObjectIDs to array twice

I am working on a table planner application where guests can be assigned to tables. The table model has the following Schema:

const mongoose = require('mongoose');

mongoose.Promise = global.Promise;

const tableSchema = new mongoose.Schema({
  name: {
    type: String,
    required: 'Please provide the name of the table',
    trim: true,
  },
  capacity: {
    type: Number,
    required: 'Please provide the capacity of the table',
  },
  guests: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Guest',
  }],
});

module.exports = mongoose.model('Table', tableSchema);

Guests can be dragged and dropped in the App (using React DND) to "Table" React components. Upon being dropped on a table, an Axios POST request is made to a Node.js method to update the Database and add the guest's Object ID to an array within the Table model:

exports.updateTableGuests = async (req, res) => {
  console.log(req.body.guestId);
  await Table.findOneAndUpdate(
    { name: req.body.tablename },
    { $push: { guests: req.body.guestId } },
    { safe: true, upsert: true },
    (err) => {
      if (err) {
        console.log(err);
      } else {
      // do stuff
      }
    },
  );
  res.send('back');
};

This is working as expected, except that with each dropped guest, the Table model's guests array is updated with the same guest Object ID twice? Does anyone know why this would be?

I have tried logging the req.body.guestID to ensure that it is a single value and also to check that this function is not being called twice. But neither of those tests brought unexpected results. I therefore suspect something is wrong with my findOneAndUpdate query?

like image 849
James Howell Avatar asked Jan 29 '23 02:01

James Howell


1 Answers

Don't use $push operator here, you need to use $addToSet operator instead...

The $push operator can update the array with same value many times where as The $addToSet operator adds a value to an array unless the value is already present.

exports.updateTableGuests = async (req, res) => {
  console.log(req.body.guestId);
  await Table.findOneAndUpdate(
    { name: req.body.tablename },
    { $addToSet : { guests: req.body.guestId } },
    { safe: true, upsert: true },
    (err) => {
      if (err) {
        console.log(err);
      } else {
      // do stuff
      }
    },
  );
  res.send('back');
};
like image 129
Ashh Avatar answered Feb 12 '23 08:02

Ashh