10

Schema:

var schema = new Schema({...}, {
    timestamps: true,
    id: false,
    toJSON: {
        virtuals: true,
    },
    toObject: {
        virtual: true,
    }
});
schema.virtual('updated').get(function () {
    if(typeof this.updatedAt === "undefined" && typeof this.createdAt === "undefined") return "";
    var updated = (typeof this.updatedAt === "undefined") ? this.createdAt : this.updatedAt;
    return "Updated "+moment(updated).fromNow();
});

This code was working recently - updatedAt for a particular instance comes up as August 24th, however any new edits to the document doesn't update the timestamp.

Feels like I'm missing something very silly here.

Simon Poole
  • 493
  • 1
  • 6
  • 15
  • Can you check typeof this.updatedAt? – abdulbarik Sep 14 '16 at 17:35
  • @abdulbarik typeof league.updatedAt => object – Simon Poole Sep 14 '16 at 17:37
  • I copy pasted your code and run on my server, and it is working perfectly fine with mongoose 4.6.1, So may be you are missing something somewhere else. Please mention mongoose version you are using, or any mongoose plugins. – Puneet Singh Sep 27 '16 at 14:21
  • @PuneetSingh Mongoose v.4.5.3. Further testing shows that createdAt is created successfully and is correct, however the updatedAt value is not altered if we then update the document. Here's where I'm calling the edit: https://github.com/simon--poole/EventVODS/blob/master/app/routes/api/leaguesRouter.js#L103 – Simon Poole Sep 27 '16 at 16:00
  • can check by `findOneAndUpdate()` instead of `findByIdAndUpdate()` ? – Shaishab Roy Sep 30 '16 at 11:57
  • 1
    Looks like it was a known issue in mongoose timestamps. And the fix was done 3 days ago. May be you can update the Mongoose time stamps to latest version and try it?. More information on the fix is given in this link. https://github.com/drudge/mongoose-timestamp/pull/37/commits/969ede70a1afac1872efcbc85a2e68b6d12caa1e – Praveen Kumar Sep 30 '16 at 15:23

7 Answers7

5

Can try by modify your schema like:

var schema =new Schema({..}, 
           { timestamps: { createdAt: 'createdDate',updatedAt: 'updatedDate' } 
});

for this schema timestmps will update on save(), update() and findOneAndUpdate(). so no need schema.virtual('updated')...

Process-2

added createdDate and updatedDate with Date type in your schema and update these date fields using schema plugin.

like:

var mongoose = require('mongoose'),
    Schema   = mongoose.Schema,
    SchemaPlugin = require('../helpers/schemaPlugin');
  var schema =new Schema({..},
    createdDate: {
      type: Date,
      default: Date.now
    },
    updatedDate: {
      type: Date,
      default: Date.now
    }
  });

  schema.plugin(SchemaPlugin);

in schemaPlugin.js file:

module.exports = function(schema) {

  var updateTimestemps = function(next){
    var self = this;


    if(!self.createdAt) {
      self.createdDate = new Date();
      //or self.update({},{ $set: { createdDate : new Date(), updatedDate: new Date() } });
    } else {
      self.updatedDate= new Date();
      //or self.update({},{ $set: {updatedDate: new Date() } });
    }
    next();
  };

  schema.
    pre('save', updateTimestemps ).
    pre('update', updateTimestemps ).
    pre('findOneAndUpdate', updateTimestemps);
};
Shaishab Roy
  • 16,335
  • 7
  • 50
  • 68
  • Nice! Your second suggestion is what I use. Worth mentioning the Mongoose docs [use the `.set()` method](https://mongoosejs.com/docs/middleware.html#notes) in their example, like this: `self.set({ updatedDate: new Date() });`. – Uche Ozoemena Jul 02 '20 at 18:20
3

Stumbled upon the same thing, figured out that if the property updatedAt is set on my object when I'm updating it with findOneAndUpdate() (or update()), it won't update it.

In my case, solved it by making sure updatedAt isn't set before update:

delete thing.updatedAt;

Thing.findOneAndUpdate(
  { _id : thing._id },
  thing,
  function (err, result) {
   …

Credit to Valeri Karpov for his answer on Github.

Maen
  • 10,603
  • 3
  • 45
  • 71
1

updatedAt and createdAt both created on same time when a new document is entered into the database using mongoose so your checking of whether updatedAt is undefined or not is illogical as both will have the same value when new document is created.

Whenever you use a mongoose update function or findByIdAndUpdate or findOneAndUpdate the value of the updatedAt will be updated automatically.Use Mongodb client like mongochef or robomongo to directly check the value of the updatedAt.

kshitij agrawal
  • 149
  • 1
  • 5
  • The update function does not automatically updates `updatedAt`. If it does, then version `5.10.15` has a bug. – Sylar Nov 22 '20 at 10:27
1

I have facing this issue too. I solved it by move {timestamps: true} after schema structure. So it becomes like this:

enter image description here

Rickyz
  • 11
  • 2
  • Please post your code directly to the answer, no need of adding extra URLs that can become invalid in future. – Tyler2P Jul 27 '23 at 19:12
1

use create method on model to get timestamps on doc creation const item = await Items.create({})

i faced the same issue and it worked for me.

i guess new keyword doesn't work, dunno why.

Maaz Ahmed
  • 11
  • 2
0

You are comparing object with String, that's why condition is false always

schema.virtual('updated').get(function () {
    if(typeof this.updatedAt === undefined && typeof this.createdAt === undefined) return "";
    var updated = (typeof this.updatedAt === undefined) ? this.createdAt : this.updatedAt;
    return "Updated "+moment(updated).fromNow();
});

Try this, it should work

abdulbarik
  • 6,101
  • 5
  • 38
  • 59
  • Thanks for the answer, but the issue doesn't seem to be with that part - the issue is with the updatedAt timestamp not updating on edit. – Simon Poole Sep 14 '16 at 17:48
  • in which place you are stuck? – abdulbarik Sep 14 '16 at 17:49
  • The Mongoose timestamp, updatedAt, is stuck at the same time - despite me updating the document since then. `updatedAt: "2016-08-24T12:28:39.842Z",`. The function to get the time _since_ then works fine. – Simon Poole Sep 14 '16 at 17:50
0

I did this await Wallpaper.create(data, {session}) instead of

let wallpaper = new Wallpaper(data, { session })
wallpaper = await wallpaper.save()

and it works for me.

Sanket Vanani
  • 244
  • 3
  • 7