Is there a way to add created_at and updated_at fields to a mongoose schema, without having to pass them in everytime new MyModel() is called?
The created_at field would be a date and only added when a document is created. The updated_at field would be updated with new date whenever save() is called on a document.
I have tried this in my schema, but the field does not show up unless I expcitly add it:
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true }
, created_at : { type: Date, required: true, default: Date.now }
});
This is what I ended up doing:
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true }
, created_at : { type: Date }
, updated_at : { type: Date }
});
ItemSchema.pre('save', function(next){
now = new Date();
this.updated_at = now;
if ( !this.created_at ) {
this.created_at = now;
}
next();
});
If you are using ObjectId as your identity field you don't need created_at
field. ObjectIds have a method called getTimestamp()
.
ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp()
This will return the following output:
ISODate("2012-10-15T21:26:17Z")
More info here How do I extract the created date out of a Mongo ObjectID
In order to add updated_at
filed you need to use this:
var ArticleSchema = new Schema({
updated_at: { type: Date }
// rest of the fields go here
});
ArticleSchema.pre('save', function(done) {
this.updated_at = new Date();
done();
});
This is how I achieved having created and updated.
Inside my schema I added the created and updated like so:
/** * Article Schema */ var ArticleSchema = new Schema({ created: { type: Date, default: Date.now }, updated: { type: Date, default: Date.now }, title: { type: String, default: '', trim: true, required: 'Title cannot be blank' }, content: { type: String, default: '', trim: true }, user: { type: Schema.ObjectId, ref: 'User' } });
Then in my article update method inside the article controller I added:
/** * Update a article */ exports.update = function(req, res) { var article = req.article; article = _.extend(article, req.body); article.set("updated", Date.now()); article.save(function(err) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); };
The bold sections are the parts of interest.
You can use the timestamp
plugin of mongoose-troop
to add this behavior to any schema.
If use update()
or findOneAndUpdate()
with {upsert: true}
option
you can use $setOnInsert
var update = {
updatedAt: new Date(),
$setOnInsert: {
createdAt: new Date()
}
};
You can use middleware and virtuals. Here is an example for your updated_at
field:
ItemSchema.virtual('name').set(function (name) {
this.updated_at = Date.now;
return name;
});