Timestamps时间戳
Mongoose schemas support a Mongoose模式支持timestamps
option. timestamps
选项。If you set 如果您设置timestamps: true
, Mongoose will add two properties of type Date
to your schema:timestamps: true
,Mongoose将向您的模式中添加两个Date
类型的属性:
createdAt
: a date representing when this document was created:表示创建此文档的日期updatedAt
: a date representing when this document was last updated:表示此文档上次更新的日期
Mongoose will then set 然后,Mongoose将在首次插入文档时设置createdAt
when the document is first inserted, and update updatedAt
whenever you update the document using save()
, updateOne()
, updateMany()
, findOneAndUpdate()
, update()
, replaceOne()
, or bulkWrite()
.createdAt
,并在使用save()
、updateOne()
、updateMany()
、findOneAndUpdate()
、update()
、replaceOne()
或bulkWrite()
更新文档时更新updatedAt
。
const userSchema = new Schema({ name: String }, { timestamps: true });
const User = mongoose.model('User', userSchema);
let doc = await User.create({ name: 'test' });
console.log(doc.createdAt); // 2022-02-26T16:37:48.244Z
console.log(doc.updatedAt); // 2022-02-26T16:37:48.244Z
doc.name = 'test2';
await doc.save();
console.log(doc.createdAt); // 2022-02-26T16:37:48.244Z
console.log(doc.updatedAt); // 2022-02-26T16:37:48.307Z
doc = await User.findOneAndUpdate({ _id: doc._id }, { name: 'test3' }, { new: true });
console.log(doc.createdAt); // 2022-02-26T16:37:48.244Z
console.log(doc.updatedAt); // 2022-02-26T16:37:48.366Z
The createdAt
property is immutable, and Mongoose overwrites any user-specified updates to updatedAt
by default.createdAt
属性是不可变的,默认情况下Mongoose会将任何用户指定的更新覆盖到updatedAt
。
let doc = await User.create({ name: 'test' });
console.log(doc.createdAt); // 2022-02-26T17:08:13.930Z
console.log(doc.updatedAt); // 2022-02-26T17:08:13.930Z
doc.name = 'test2';
doc.createdAt = new Date(0);
doc.updatedAt = new Date(0);
await doc.save();
// Mongoose blocked changing `createdAt` and set its own `updatedAt`, ignoring
// the attempt to manually set them.
console.log(doc.createdAt); // 2022-02-26T17:08:13.930Z
console.log(doc.updatedAt); // 2022-02-26T17:08:13.991Z
// Mongoose also blocks changing `createdAt` and sets its own `updatedAt`
// on `findOneAndUpdate()`, `updateMany()`, and other query operations
doc = await User.findOneAndUpdate(
{ _id: doc._id },
{ name: 'test3', createdAt: new Date(0), updatedAt: new Date(0) },
{ new: true }
);
console.log(doc.createdAt); // 2022-02-26T17:08:13.930Z
console.log(doc.updatedAt); // 2022-02-26T17:08:14.008Z
Alternate Property Names备用属性名称
For the purposes of these docs, we'll always refer to 出于这些文档的目的,我们将始终引用createdAt
and updatedAt
. But you can overwrite these property names as shown below.createdAt
和updatedAt
。但是您可以覆盖这些属性名称,如下所示。
const userSchema = new Schema({ name: String }, {
timestamps: {
createdAt: 'created_at', // Use `created_at` to store the created date
updatedAt: 'updated_at' // and `updated_at` to store the last updated date
}
});
Disabling Timestamps禁用时间戳
save()
, updateOne()
, updateMany()
, findOneAndUpdate()
, update()
, replaceOne()
, and bulkWrite()
all support a timestamps
option. save()
、updateOne()
、updateMany()
、findOneAndUpdate()
、update()
、replaceOne()
和bulkWrite()
都支持timestamps
选项。Set 设置timestamps: false
to skip setting timestamps for that particular operation.timestamps: false
可跳过为该特定操作设置时间戳。
let doc = await User.create({ name: 'test' });
console.log(doc.createdAt); // 2022-02-26T23:28:54.264Z
console.log(doc.updatedAt); // 2022-02-26T23:28:54.264Z
doc.name = 'test2';
// Setting `timestamps: false` tells Mongoose to skip updating `updatedAt` on this `save()`
await doc.save({ timestamps: false });
console.log(doc.updatedAt); // 2022-02-26T23:28:54.264Z
// Similarly, setting `timestamps: false` on a query tells Mongoose to skip updating
// `updatedAt`.
doc = await User.findOneAndUpdate({ _id: doc._id }, { name: 'test3' }, {
new: true,
timestamps: false
});
console.log(doc.updatedAt); // 2022-02-26T23:28:54.264Z
// Below is how you can disable timestamps on a `bulkWrite()`
await User.bulkWrite([{
updateOne: {
filter: { _id: doc._id },
update: { name: 'test4' },
timestamps: false
}
}]);
doc = await User.findOne({ _id: doc._id });
console.log(doc.updatedAt); // 2022-02-26T23:28:54.264Z
You can also set the 您还可以将timestamps
option to an object to configure createdAt
and updatedAt
separately. timestamps
选项设置为一个对象,以分别配置createdAt
和updatedAt
。For example, in the below code, Mongoose sets 例如,在下面的代码中,Mongoose在createdAt
on save()
but skips updatedAt
.save()
上设置createdAt
,但跳过updatedAt
。
const doc = new User({ name: 'test' });
// Tell Mongoose to set `createdAt`, but skip `updatedAt`.
await doc.save({ timestamps: { createdAt: true, updatedAt: false } });
console.log(doc.createdAt); // 2022-02-26T23:32:12.478Z
console.log(doc.updatedAt); // undefined
Disabling timestamps also lets you set timestamps yourself. 禁用时间戳还可以让您自己设置时间戳。For example, suppose you need to correct a document's 例如,假设您需要更正文档的createdAt
or updatedAt
property. createdAt
或updatedAt
属性。You can do that by setting 您可以通过设置timestamps: false
and setting createdAt
yourself as shown below.timestamps: false
并设置createdAt
自己来完成,如下所示。
let doc = await User.create({ name: 'test' });
// To update `updatedAt`, do a `findOneAndUpdate()` with `timestamps: false` and
// `updatedAt` set to the value you want
doc = await User.findOneAndUpdate({ _id: doc._id }, { updatedAt: new Date(0) }, {
new: true,
timestamps: false
});
console.log(doc.updatedAt); // 1970-01-01T00:00:00.000Z
// To update `createdAt`, you also need to set `strict: false` because `createdAt`
// is immutable
doc = await User.findOneAndUpdate({ _id: doc._id }, { createdAt: new Date(0) }, {
new: true,
timestamps: false,
strict: false
});
console.log(doc.createdAt); // 1970-01-01T00:00:00.000Z
Timestamps on Subdocuments子文档上的时间戳
Mongoose also supports setting timestamps on subdocuments. Mongoose还支持在子文档上设置时间戳。Keep in mind that 请记住,子文档的createdAt
and updatedAt
for subdocuments represent when the subdocument was created or updated, not the top level document. Overwriting a subdocument will also overwrite createdAt
.createdAt
和updatedAt
表示子文档的创建或更新时间,而不是顶级文档。覆盖子文档也会覆盖createdAt
。
const roleSchema = new Schema({ value: String }, { timestamps: true });
const userSchema = new Schema({ name: String, roles: [roleSchema] });
const doc = await User.create({ name: 'test', roles: [{ value: 'admin' }] });
console.log(doc.roles[0].createdAt); // 2022-02-27T00:22:53.836Z
console.log(doc.roles[0].updatedAt); // 2022-02-27T00:22:53.836Z
// Overwriting the subdocument also overwrites `createdAt` and `updatedAt`
doc.roles[0] = { value: 'root' };
await doc.save();
console.log(doc.roles[0].createdAt); // 2022-02-27T00:22:53.902Z
console.log(doc.roles[0].updatedAt); // 2022-02-27T00:22:53.902Z
// But updating the subdocument preserves `createdAt` and updates `updatedAt`
doc.roles[0].value = 'admin';
await doc.save();
console.log(doc.roles[0].createdAt); // 2022-02-27T00:22:53.902Z
console.log(doc.roles[0].updatedAt); // 2022-02-27T00:22:53.909Z
Under the Hood引擎盖下
For queries with timestamps, Mongoose adds 2 properties to each update query:对于带有时间戳的查询,Mongoose为每个更新查询添加2个属性:
Add将updatedAt
to$set
updatedAt
添加到$set
Add将createdAt
to$setOnInsert
createdAt
添加到$setOnInsert
For example, if you run the below code:例如,如果您运行以下代码:
mongoose.set('debug', true);
const userSchema = new Schema({
name: String
}, { timestamps: true });
const User = mongoose.model('User', userSchema);
await User.findOneAndUpdate({}, { name: 'test' });
You'll see the below output from Mongoose debug mode:您将看到以下来自Mongoose调试模式的输出:
Mongoose: users.findOneAndUpdate({}, { '$setOnInsert': { createdAt: new Date("Sun, 27 Feb 2022 00:26:27 GMT") }, '$set': { updatedAt: new Date("Sun, 27 Feb 2022 00:26:27 GMT"), name: 'test' }}, {...})
Notice the 注意$setOnInsert
for createdAt
and $set
for updatedAt
. createdAt
的$setOnInsert
和updatedAt
的$set
。MongoDB's MongoDB的$setOnInsert
operator applies the update only if a new document is upserted. $setOnInsert
运算符仅在新文档被upserted时应用更新。So, for example, if you want to only set 因此,例如,如果您想在创建新文档时仅在文档中设置updatedAt
if the document if a new document is created, you can disable the updatedAt
timestamp and set it yourself as shown below:updatedAt
,则可以禁用updatedAt
时间戳并自行设置,如下所示:
await User.findOneAndUpdate({}, { $setOnInsert: { updatedAt: new Date() } }, {
timestamps: { createdAt: true, updatedAt: false }
});