NodeJS, Mongoose if ID exists do nothing, if doesn't exist push the new one to the array

Viewed 75

I have User model and every user can have an array of ownerId's. I want to make an API which will push a new ownerId to the array, but if this ownerId already exists, do nothing..

I have tried $addToSet but it doesn't work.. However it works with $push, but if ownerId already exists it keeps pushing the same ownerId so i have duplicates which is not OK..

User model

const UserSchema = new mongoose.Schema({
  email: { type: String, required: true, min: 6, max: 255 },
  password: { type: String, required: true, min: 4, max: 1024 },
  role: { type: String, required: true, default: "User" },
  owners: [
    {
      type: Schema.Types.ObjectId,
      ref: "Owners",
      required: false,
    },
  ],
});

And my NodeJS Mongoose API:

exports.addOwnerToUser = async (req: Request, res: Response) => {
  try {
    let ObjectID = require("mongodb").ObjectID;

    const user = {
      email: req.body.email,
      ownerId: req.body.ownerId,
    };
    const updatedUser = await User.findOneAndUpdate(
      { _id: req.params.userId },
      {
        $push: { owners: req.body.ownerId },
      }
    );
    console.log(updatedUser);

    res.status(201).json({ sucess: true, msg: "User updated sucessfully" });
  } catch (err) {
    res.status(404).json(err);
  }
};

Thanks

4 Answers

$push will just push data in array, in your case you should use $addToSet

$addToSet only ensures that there are no duplicate items added to the set and does not affect existing duplicate elements.

 const updatedUser = await User.findOneAndUpdate({
    { _id: req.params.userId },
    'ownerId.ownerId': {
       '$ne': new mongoose.ObjectID(req.body.ownerId)
    }
   }, {
     $addToSet: {
        'ownerId.ownerId': new mongoose.ObjectID(req.body.ownerId)
     }
   }, {
     new: true
   });

just remove below query

'ownerId.ownerId': {
       '$ne': req.body.ownerId
    }

Updated code.

const updatedUser = await User.findOneAndUpdate({
    _id: req.params.userId,
   }, {
     $addToSet: {
        'ownerId.ownerId': req.body.ownerId
     }
   }, {
     new: true
   });

OR

with ownerId Query

const updatedUser = await User.findOneAndUpdate({
    _id: req.params.userId,
    'ownerId.ownerId': {
           '$ne': req.body.ownerId
        }
   }, {
     $push: {
        'ownerId': {ownerId: req.body.ownerId }
     }
   }, {
     new: true
   });

Your schema design is not right, that is why $addToSet is not working for you.

so, if you want multiple owners in the user object please change your schema design to this

const UserSchema = new mongoose.Schema({
  email: { type: String, required: true, min: 6, max: 255 },
  password: { type: String, required: true, min: 4, max: 1024 },
  role: { type: String, required: true, default: "User" },
  owners: [{
        type: Schema.Types.ObjectId,
        ref: "Owners",
        required: false,
     }],
});

After this use $addToSet to add the new owner id in the user object

User.findOneAndUpdate(
   { _id: req.params.userId },
   { $addToSet: { owners: req.body.ownerId } }
 )

it will not add the duplicates For Reference: https://www.mongodb.com/docs/manual/reference/operator/update/addToSet/

Note: As per my previous experience with this kind of work, it is better if you change the key ownerId to owners because in general these are the owners array not the ownerId

Try this:

exports.addOwnerToUser = async (req: Request, res: Response) => {
    try {
        let ObjectID = require("mongodb").ObjectID;

        const user = {
            email: req.body.email,
            ownerId: req.body.ownerId,
        };
        const updatedUser = await User.findOne({
                _id: req.params.userId
            })
            .then(user => {
                if (user.ownerId[0]) {
                    user.ownerId[0].ownerId = req.body.ownerId;
                }
            })
        console.log(updatedUser);

        res.status(201).json({
            sucess: true,
            msg: "User updated sucessfully"
        });
    } catch (err) {
        res.status(404).json(err);
    }
};
Related