将created_at和updated_at字段添加到mongoose模式
有没有办法将created_at和updated_at字段添加到mongoose模式中,而不必每次都传递新的MyModel()被调用?
created_at字段将是一个date,并且仅在创build文档时添加。 只要在文档上调用save(),updated_at字段就会用新的date更新。
我在我的模式中试过这个,但是除非我用expcitly添加它,否则这个字段不会显示出来:
var ItemSchema = new Schema({ name : { type: String, required: true, trim: true } , created_at : { type: Date, required: true, default: Date.now } });
如果使用update()
或findOneAndUpdate()
与{upsert: true}
选项
你可以使用$setOnInsert
var update = { updatedAt: new Date(), $setOnInsert: { createdAt: new Date() } };
更新: (4年后)
如果你使用ObjectId
作为你的_id
字段(这通常是这种情况),那么你所要做的就是:
let document = { updatedAt: new Date(), }
检查我的原始答案如何从_id
字段获取创build的时间戳。 如果您需要使用外部系统的ID,请检查Roman Rhrn Nesterov的答案。
更新: (2.5年后)
您现在可以使用mongoose版本> = 4.0的#timestamps选项。
let ItemSchema = new Schema({ name: { type: String, required: true, trim: true } }, { timestamps: true });
如果设置了时间戳,mongoose将updatedAt
和updatedAt
字段分配给您的模式,分配的types是Date
。
您还可以指定时间戳文件的名称:
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
注意:如果您正在处理关键数据的大型应用程序,则应重新考虑更新文档。 我build议你使用不可变的,只能追加的数据( lambda体系结构 )。 这意味着你只允许插入。 更新和删除不应该被允许! 如果你想“删除”一个logging,你可以很容易地插入一个新的版本的文件与一些
timestamp
/version
领域,然后设置deleted
字段为true
。 同样的,如果你想更新一个文件 – 你创build一个新的适当的领域更新,其余的领域复制over.Then为了查询这个文件,你会得到最新的时间戳或最高版本是不是“删除”(deleted
字段是undefined或false)。数据不可变性确保您的数据是可debugging的 – 您可以跟踪每个文档的历史logging。 如果出现问题,您也可以回滚到文档的以前版本。 如果你使用这样的体系结构
ObjectId.getTimestamp()
是你所需要的,它不是Mongoose的依赖。
原文答案:
如果您使用ObjectId作为标识字段,则不需要created_at
字段。 ObjectIds有一个名为getTimestamp()
的方法。
的ObjectId( “507c7f79bcf86cd7994f6c0e”)。getTimestamp()
这将返回以下输出:
ISODate( “2012-10-15T21:26:17Z”)
更多信息在这里如何从Mongo ObjectID中提取创build的date
为了添加updated_at
文件,你需要使用这个:
var ArticleSchema = new Schema({ updated_at: { type: Date } // rest of the fields go here }); ArticleSchema.pre('save', function(next) { this.updated_at = Date.now(); next(); });
这就是我最终做的事情:
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(); });
为您的模式使用内置的timestamps
选项。
var ItemSchema = new Schema({ name: { type: String, required: true, trim: true } }, { timestamps: true });
这会自动将updatedAt
和updatedAt
字段添加到您的模式。
从Mongoose 4.0开始,你现在可以在Schema上设置一个时间戳选项来让Mongoose为你处理:
var thingSchema = new Schema({..}, { timestamps: true });
您可以更改所使用的字段的名称,如下所示:
var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });
我就是这样创build和更新的。
在我的模式中,我添加了创build和更新,如下所示:
/ ** *文章模式 * / var ArticleSchema = new Schema({ 创build:{ 键入:date, 默认值:Date.now }, 更新: { 键入:date, 默认值:Date.now }, 标题:{ 键入:String, 默认:'', 修剪:真实的, 要求:'标题不能为空' }, 内容:{ 键入:String, 默认:'', 修剪:真实 }, 用户:{ 键入:Schema.ObjectId, ref:'User' } });
然后在我的文章更新方法里面的文章控制器我补充说:
/ ** *更新文章 * / exports.update = function(req,res){ var article = req.article; article = _.extend(article,req.body); article.set(“updated”,Date.now()); article.save(function(err){ 如果(err){ 返回res.status(400).send({ 消息:errorHandler.getErrorMessage(err) }); } else { res.json(物品); } }); };
大胆的部分是感兴趣的部分。
您可以使用mongoose-troop
的timestamp
插件将此行为添加到任何架构。
添加timestamps
到你的Schema
然后这样updatedAt
和updatedAt
会自动为你生成
var UserSchema = new Schema({ email: String, views: { type: Number, default: 0 }, status: Boolean }, { timestamps: {} });
你也可以通过改变createdAt -> created_at
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
你可以很容易地使用这个插件 。 从文档:
var timestamps = require('mongoose-timestamp'); var UserSchema = new Schema({ username: String }); UserSchema.plugin(timestamps); mongoose.model('User', UserSchema); var User = mongoose.model('User', UserSchema)
如果您愿意,还可以设置字段的名称:
mongoose.plugin(timestamps, { createdAt: 'created_at', updatedAt: 'updated_at' });
我们也可以通过使用Schema插件来实现这一点。
在helpers/schemaPlugin.js
文件中
module.exports = function(schema) { var updateDate = function(next){ var self = this; self.updated_at = new Date(); if ( !self.created_at ) { self.created_at = now; } next() }; // update date for bellow 4 methods schema.pre('save', updateDate) .pre('update', updateDate) .pre('findOneAndUpdate', updateDate) .pre('findByIdAndUpdate', updateDate); };
并在models/ItemSchema.js
文件中:
var mongoose = require('mongoose'), Schema = mongoose.Schema, SchemaPlugin = require('../helpers/schemaPlugin'); var ItemSchema = new Schema({ name : { type: String, required: true, trim: true }, created_at : { type: Date }, updated_at : { type: Date } }); ItemSchema.plugin(SchemaPlugin); module.exports = mongoose.model('Item', ItemSchema);
const mongoose = require('mongoose'); const config = require('config'); const util = require('util'); const Schema = mongoose.Schema; const BaseSchema = function(obj, options) { if (typeof(options) == 'undefined') { options = {}; } if (typeof(options['timestamps']) == 'undefined') { options['timestamps'] = true; } Schema.apply(this, [obj, options]); }; util.inherits(BaseSchema, Schema); var testSchema = new BaseSchema({ jsonObject: { type: Object } , stringVar : { type: String } });
现在你可以使用这个,所以不需要在每个表中包含这个选项
我的mongoose版本是4.10.2
似乎只有钩子findOneAndUpdate
工作
ModelSchema.pre('findOneAndUpdate', function(next) { // console.log('pre findOneAndUpdate ....') this.update({},{ $set: { updatedAt: new Date() } }); next() })
我其实是在后面做这个
如果一切顺利进行更新:
// All ifs passed successfully. Moving on the Model.save Model.lastUpdated = Date.now(); // <------ Now! Model.save(function (err, result) { if (err) { return res.status(500).json({ title: 'An error occured', error: err }); } res.status(200).json({ message: 'Model Updated', obj: result }); });
使用函数返回计算出的默认值:
var ItemSchema = new Schema({ name: { type: String, required: true, trim: true }, created_at: { type: Date, default: function(){ return Date.now(); } }, updated_at: { type: Date, default: function(){ return Date.now(); } } }); ItemSchema.pre('save', function(done) { this.updated_at = Date.now(); done(); });
你可以使用中间件和虚拟 。 以下是updated_at
字段的示例:
ItemSchema.virtual('name').set(function (name) { this.updated_at = Date.now; return name; });