Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose findOneAndUpdate when value is not in array

I have the below Mongoose function where I am trying to do a select WHERE email = req.body.email and referenceId is not in an array.

referenceId is a string array [String] which has an array of object ID's.

const refereeSchema = new Schema({
  firstName: {
    type: String,
    required: true
  },
  lastName: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  referenceId: [
    {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    }
  ],
  token: {
    type: String,
    required: true
  },
  password: {
    type: String
  },
  company: {
    type: String,
    required: true
  },
  role: {
    type: String,
    required: false
  },
  startedOn: Date,
  endedOn: Date,
  createdAt: Date,
  updatedAt: Date
});


  Referee.findOneAndUpdate({
    email: req.body.email,
    referenceId: {
      '$ne': [new mongo.ObjectID(req.params.referenceId)]
    }
  }, {
    $push: {
      referenceId: new mongo.ObjectID(req.body.referenceId)
    }
  }, {
    new: true
  }, (err, doc) => {
    if (err) {
      res.status(401).send(err);
    }
    res.send(doc);
  });

Each time I run the above it always matches and pushes the ObjectId even though it already existed before.

{ referenceId:
   [ 5ba94232b492890982e7a417,
     5ba94232b492890982e7a417,
     5c20d8f907a55accd720c27f,
     5c20d8f907a55accd720c27f,
     5c20d8f907a55accd720c27f,
     5c20d8f907a55accd720c27f,
     5c20d8f907a55accd720c27f,
     5c20d8f907a55accd720c27f ],
  _id: 5c20e86d72d5c1ce20b961fa,
  firstName: 'Richard',
  lastName: 'Hendricks',
  email: '[email protected]',
  token: '319d9f5a-68e1-6f47-a9f1-7fbbf617a45c',
  company: 'Pied Piper',
  role: '',
  __v: 0 }

Could someone please help me?

I'd like to do a check to see if the ObjectId is already in the array then DO NOTHING else push it.


2 Answers

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

$addToSet only ensures that there are no duplicate items added to the set and does not affect existing duplicate elements. $addToSet does not guarantee a particular ordering of elements in the modified set

more details

Referee.findOneAndUpdate({
    email: req.body.email,
    referenceId: {
       '$ne': [new mongo.ObjectID(req.params.referenceId)]
    }
   }, {
     $addToSet: {
        referenceId: new mongo.ObjectID(req.body.referenceId)
     }
   }, {
     new: true
   }, (err, doc) => {
     if (err) {
        res.status(401).send(err);
     }
     res.send(doc);
 });

more ever, you can use $elemMatch or $nin as find query, so that document itself doesnt return if id is in referenceId

$elemMatch :

referenceId: {
  '$elemMatch': { '$ne': new mongo.ObjectID(req.params.referenceId) }
}

$nin:

referenceId: {
   '$nin': [new mongo.ObjectID(req.params.referenceId)]
}
like image 101
the_mahasagar Avatar answered Oct 21 '25 23:10

the_mahasagar


Consider using the $elemMatch operator in complement of $ne. $ne against the array itself will always return true in this case, because the array you're passing in the parameter is never going to equal the array in the document.

I haven't tested this, but something along these lines should work:

Referee.findOneAndUpdate({
    email: req.body.email,
    referenceId: {
      '$elemMatch': { '$ne': new mongo.ObjectID(req.params.referenceId) }
    }
  }, {
    $push: {
      referenceId: new mongo.ObjectID(req.body.referenceId)
    }
  }, {
    new: true
  }, (err, doc) => {
    if (err) {
      res.status(401).send(err);
    }
    res.send(doc);
  });

Also, you probably already know this but there are actually two ObjectId classes you might be importing, the one you want is mongoose.Types.ObjectId

like image 32
Paul Avatar answered Oct 21 '25 22:10

Paul



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!