15

My application uses Mongoose and has a schema that uses the timestamps option:

var fooSchema = new Schema({
    name: String,
}, {
    timestamps: true,
});
mongoose.model('Foo', fooSchema);

So whenever an update is written to the collection, the updatedAt property is changed to the current date. But now I would like to add some changes that should not update the updatedAt property. Some answers on Stackoverflow (example) suggested to use Foo.collection as that allegedly accesses the native MongoDB driver. So I tried this:

Foo.collection.update({ _id: someFooId }, { $set: { name: 'New Name' } });

However, that changed the updatedAt property as well.

So how can I update a document, without changing updatedAt?

str
  • 42,689
  • 17
  • 109
  • 127
  • I have this same exact problem. Did you ever find a solution/workaround for this? – danii Mar 10 '17 at 12:14
  • 1
    @danii No unfortunately not. I removed the timestamps middleware and update the timestamps manually where necessary. – str Mar 10 '17 at 12:29

3 Answers3

12

I just found a solution and it works perfectly to me.

mongoose.connection.db.collection('player').updateOne(
    {_id: mongoose.Types.ObjectId('56cb91sf34746f14678934ba')},
    {$set: {name: 'Test'}}
);

This query will not update the updatedAt field. Hope you still need this!

Emilio Venegas
  • 546
  • 5
  • 22
  • 3
    two years later, face the same issue, google for answers, find old thread w/my comments on it (which I had of course completely forgotten about), get completely valid answer. Gotta love Stackoverflow :) Edit: This answer should be accepted, it's perfect for this usecase. No it's never too late, thanks!! – danii Feb 07 '19 at 09:36
  • I don't think this is a good solution, as you're accessing the driver to bypass the middleware. This will also skip validations and other features. https://stackoverflow.com/a/64634344/1496274 seems to be the solution if you're using Mongoose 5+ – Danilo Freitas Nov 09 '22 at 12:34
12

From mongoose 5 onwards , there is timestamps option which can be passed in Model.updateOne() and model.update() to skip timestamps for this update.

Directly from docs:

[options.timestamps=null] «Boolean» If set to false and schema-level timestamps are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.

For example given in the question , timestamp updates can be skipped like this ,

Foo.updateOne({ __id: someFooId },{ $set: { name: updatedName } }, { timestamps: false });
str
  • 42,689
  • 17
  • 109
  • 127
parth_07
  • 1,322
  • 16
  • 22
-1

What i can get is you are automatically updating the dateTime of updated_at field. You must be passing a default value for the updated_at in your schema, just remove that default field.

For example.

var fooSchema = new Schema({
    name: String,
}, {
    updated_at:{
         type: Date,
         default: Date.now
    }
});
mongoose.model('Foo', fooSchema);

Remove the default field from updated_at and your schema will look like this.

var fooSchema = new Schema({
    name: String,
}, {
    updated_at: Date
});
mongoose.model('Foo', fooSchema);
Rahul Kumar
  • 5,120
  • 5
  • 33
  • 44
Ajitej Kaushik
  • 932
  • 9
  • 30
  • "You must be passing a default value for the updated_at in your schema" No, the posted schema is the complete one. And the second parameter of `Schema` is for options, there is not `updated_at` option, though. – str Jul 28 '16 at 06:30
  • then how is your `updatedAt` field is getting updated if there is no such key present? ps. i put `updated_at` in reference to your `updatedAt` only. – Ajitej Kaushik Jul 28 '16 at 06:39
  • See [timestamp options](http://mongoosejs.com/docs/guide.html#timestamps) as mentioned in the question. – str Jul 28 '16 at 06:42
  • Ok, instead of using it, you should pass `updatedAt` key directly into your schema as using `timestamps` will auto update everytime you update the document. You can refer the schema i mentioned. – Ajitej Kaushik Jul 28 '16 at 06:48
  • Yes that is possible of course. But I would like to avoid updating it manually. – str Jul 28 '16 at 06:49
  • You need not let user pass the value evrytime but whenever you want to update the field, just pass `fooSchema.updatedAt = Date.now` in your routes where you are exporting the schema. – Ajitej Kaushik Jul 28 '16 at 06:51
  • I do know that. But I still would like to avoid that as it may be forgotten. It should always be updated automatically, except for a small set of queries. – str Jul 28 '16 at 07:14
  • 1
    Downvoted as this answer misses the `timestamp: true` feature and thus is not helpful. – gustavopch Dec 15 '18 at 21:15