Simon Poole
Simon Poole

Reputation: 513

MongoDB / Mongoose timestamps not updating

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.

Upvotes: 11

Views: 17927

Answers (7)

Sanket Vanani
Sanket Vanani

Reputation: 546

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.

Upvotes: 0

Maaz Ahmed
Maaz Ahmed

Reputation: 11

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.

Upvotes: 1

Rickyz
Rickyz

Reputation: 11

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

Upvotes: 1

Maen
Maen

Reputation: 10698

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.

Upvotes: 3

kshitij agrawal
kshitij agrawal

Reputation: 149

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.

Upvotes: 1

Shaishab Roy
Shaishab Roy

Reputation: 16805

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);
};

Upvotes: 5

abdulbari
abdulbari

Reputation: 6242

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

Upvotes: 0

Related Questions