Sayak Mukhopadhyay
Sayak Mukhopadhyay

Reputation: 1464

Modifying mongoose document on pre hook of findOneAndUpdate()

I have a mongoose schema as such

var schema = new Schema({
    id:Number
    updated_at:Date
});

I am using findOneAndUpdate() to update this model as such

model.findOneAndUpdate(
    { id: json.id },
    json,
    {
        upsert: true,
        runValidators: true
    })
    .then(() => {
        recordsUpdated++;
    })
    .catch((err) => {
        this.emit('error', err);
    });

The value being passed in json is not correct and I need to make some modifications to it. I am looking for a pre hook to do the modification. I have tried

faction.pre('findOneAndUpdate', function (next) {
   this.update({ $set: { updated_at: this.getUpdate().updated_at * 1000 } });
   next();
});

In short I want to convert the timestamp which is in seconds to milliseconds before updating the database, but this doesn't work.

Upvotes: 6

Views: 6697

Answers (3)

Ibad Shah
Ibad Shah

Reputation: 539

Update "mongoose": "^6.4.0"

Thanks to the above top-rated solution, what worked for me was

this._update.$set.updated_at = new Date();

In my case, I wanted to save the currency key as uppercase if it is available in the requested object.

schema.pre('findOneAndUpdate', async function (next) {
  const currency = this?._update?.$set?.currency;
  if (currency) {
    this.set({ currency: currency.toUpperCase() });
  }
  next();
});

Upvotes: 0

Alon Malivanchuk
Alon Malivanchuk

Reputation: 271

Better solution is like this:

schema.pre('findOneAndUpdate', function (this, next) {
    this.update().updated_at *= 1000;
    next();
});

Upvotes: 0

Sayak Mukhopadhyay
Sayak Mukhopadhyay

Reputation: 1464

After blindly throwing stones all around, what worked for me was

schema.pre('findOneAndUpdate', function (next) {
    this._update.updated_at *= 1000;
    next();
});

In short one needs to modify the document present in the _update property.

Upvotes: 22

Related Questions