有没有办法将created_at和updated_at字段添加到mongoose模式,而不必在每次调用新的MyModel()时都传递它们?
created_at字段将是一个日期,仅在创建文档时添加。 每当在文档上调用save()时,updated_at字段将使用新日期进行更新。
我在我的架构中尝试了这个,但除非我明确地添加它,否则该字段不会显示:
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true }
, created_at : { type: Date, required: true, default: Date.now }
});
答案 0 :(得分:224)
更新:(5年后)
注意:如果您决定使用Kappa Architecture(事件采购+ CQRS ),则根本不需要更新日期。由于您的数据是一个不可变的仅附加事件日志,因此您只需要事件创建日期。与 Lambda Architecture 类似,如下所述。然后,您的应用程序状态是事件日志(派生数据)的投影。如果您收到有关现有实体的后续事件,则您将使用该事件的创建日期作为您实体的更新日期。这是微服务系统中常用的(通常被误解的)实践。
更新:(4年后)
如果您使用ObjectId
作为_id
字段(通常是这种情况),那么您需要做的就是:
let document = {
updatedAt: new Date(),
}
检查下面的原始答案,了解如何从_id
字段获取创建的时间戳。
如果您需要使用外部系统的ID,请查看Roman Rhrn Nesterov的答案。
更新:(2。5年后)
现在,您可以使用#timestamps选项与mongoose版本> = 4.0。
let ItemSchema = new Schema({
name: { type: String, required: true, trim: true }
},
{
timestamps: true
});
如果设置了时间戳,则mongoose会为您的架构分配createdAt
和updatedAt
字段,分配的类型为Date
。
您还可以指定时间戳文件名称:
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
注意:如果您正在处理包含关键数据的大型应用程序,则应重新考虑更新文档。我建议你使用不可变的,仅附加数据(lambda architecture)。这意味着什么 你只允许插入。 不应该更新和删除 允许!如果你想“删除”一条记录,你可以很容易 使用一些
timestamp
/version
插入新版本的文档 提交,然后将deleted
字段设置为true
。同样如果你想 更新文档 - 您使用适当的文档创建一个新文档 字段已更新,其余字段已复制。然后为了 查询此文档,您将获得具有最新时间戳的那个或 未被“删除”的最高版本(deleted
字段未定义或为false)。数据不变性可确保您的数据可调试 - 您可以跟踪 每个文件的历史。您也可以回滚到之前的版本 如果出现问题,文档的版本。如果你去这样的话 架构
ObjectId.getTimestamp()
就是你所需要的,而事实并非如此 依赖猫鼬。
原始答案:
如果您使用ObjectId作为您的身份字段,则不需要created_at
字段。 ObjectIds有一个名为getTimestamp()
的方法。
ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp()
这将返回以下输出:
ISODate("2012-10-15T21:26:17Z")
此处有更多信息How do I extract the created date out of a Mongo ObjectID
要添加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();
});
答案 1 :(得分:129)
这就是我最终做的事情:
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();
});
答案 2 :(得分:102)
对Schema使用内置timestamps
选项。
var ItemSchema = new Schema({
name: { type: String, required: true, trim: true }
},
{
timestamps: true
});
这会自动将createdAt
和updatedAt
字段添加到您的架构中。
答案 3 :(得分:69)
从Mongoose 4.0开始,您现在可以在Schema上设置一个时间戳选项,让Mongoose为您处理:
var thingSchema = new Schema({..}, { timestamps: true });
您可以更改使用的字段名称:
var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });
答案 4 :(得分:28)
如果使用update()
或findOneAndUpdate()
使用{upsert: true}
选项
您可以使用$setOnInsert
var update = {
updatedAt: new Date(),
$setOnInsert: {
createdAt: new Date()
}
};
答案 5 :(得分:23)
将timestamps
添加到您的Schema
,然后createdAt
和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' }
答案 6 :(得分:8)
这是我创建和更新的方式。
在我的架构中,我添加了创建和更新,如下所示:
/** * 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' } });
然后在文章控制器里面的文章更新方法中我添加了:
/** * 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); } }); };
粗体部分是感兴趣的部分。
答案 7 :(得分:4)
您可以使用mongoose-troop
的{{3}}插件将此行为添加到任何架构中。
答案 8 :(得分:3)
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true }
});
ItemSchema.set('timestamps', true); // this will add createdAt and updatedAt timestamps
答案 9 :(得分:2)
您可以非常轻松地使用this plugin。 来自文档:
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'
});
答案 10 :(得分:1)
我们也可以通过架构插件来实现这一点。
在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);
答案 11 :(得分:1)
对于带有 Mongoose 的 NestJs,使用这个
@Schema({timestamps: true})
答案 12 :(得分:1)
从mongo 3.6开始,您可以使用“更改流”: https://emptysqua.re/blog/driver-features-for-mongodb-3-6/#change-streams
要使用它,您需要通过“监视”查询创建一个变更流对象,对于每个变更,您都可以做任何您想做的事...
python解决方案:
def update_at_by(change):
update_fields = change["updateDescription"]["updatedFields"].keys()
print("update_fields: {}".format(update_fields))
collection = change["ns"]["coll"]
db = change["ns"]["db"]
key = change["documentKey"]
if len(update_fields) == 1 and "update_at" in update_fields:
pass # to avoid recursion updates...
else:
client[db][collection].update(key, {"$set": {"update_at": datetime.now()}})
client = MongoClient("172.17.0.2")
db = client["Data"]
change_stream = db.watch()
for change in change_stream:
print(change)
update_ts_by(change)
注意,要使用change_stream对象,您的mongodb实例应以“副本集”运行。 也可以将其作为1节点副本集来完成(几乎没有变化,只有独立使用):
将mongo作为副本集运行: https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set/
副本集配置与独立版: Mongo DB - difference between standalone & 1-node replica set
答案 13 :(得分:1)
在模型架构中,只需添加属性时间戳并为其分配值 true 即可,如下所示:-
var ItemSchema = new Schema({
name : { type: String, required: true, trim: true },
},{timestamps : true}
);
答案 14 :(得分:1)
我的猫鼬版本是4.10.2
似乎只有钩子findOneAndUpdate
正在工作
ModelSchema.pre('findOneAndUpdate', function(next) {
// console.log('pre findOneAndUpdate ....')
this.update({},{ $set: { updatedAt: new Date() } });
next()
})
答案 15 :(得分:0)
我实际上在后面这样做
如果更新一切顺利:
// 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
});
});
答案 16 :(得分:0)
使用machinepack-datetime格式化日期时间。
tutorialSchema.virtual('createdOn').get(function () {
const DateTime = require('machinepack-datetime');
let timeAgoString = "";
try {
timeAgoString = DateTime.timeFrom({
toWhen: DateTime.parse({
datetime: this.createdAt
}).execSync(),
fromWhen: new Date().getTime()
}).execSync();
} catch(err) {
console.log('error getting createdon', err);
}
return timeAgoString; // a second ago
});
与快速或一般的Javascript世界不同,机器包具有清晰的API。
答案 17 :(得分:0)
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 }
});
现在您可以使用它,这样就不需要在每个表中包含此选项
答案 18 :(得分:0)
如果您使用 nestjs 和 @Schema 装饰器,您可以像这样实现:
@Schema({
timestamps: true,
})
时间戳选项告诉猫鼬将 createdAt 和 updatedAt 字段分配给您的架构。分配的类型是日期。
默认情况下,字段的名称是 createdAt 和 updatedAt。
通过设置 timestamps.createdAt 和 timestamps.updatedAt 来自定义字段名称。
答案 19 :(得分:-1)
使用函数返回计算的默认值:
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();
});
答案 20 :(得分:-3)
您可以使用middleware和virtuals。以下是updated_at
字段的示例:
ItemSchema.virtual('name').set(function (name) {
this.updated_at = Date.now;
return name;
});