如果您正在寻找预期行为的“证据”,那么只需查看源代码本身即可。特别是schema.js main definition内:
updates.$setOnInsert = {};
updates.$setOnInsert[createdAt] = now;
}
return updates;
};
this.methods.initializeTimestamps = function() {
if (createdAt && !this.get(createdAt)) {
this.set(createdAt, new Date());
}
if (updatedAt && !this.get(updatedAt)) {
this.set(updatedAt, new Date());
}
return this;
};
this.pre('findOneAndUpdate', _setTimestampsOnUpdate);
this.pre('update', _setTimestampsOnUpdate);
this.pre('updateOne', _setTimestampsOnUpdate);
this.pre('updateMany', _setTimestampsOnUpdate);
}
function _setTimestampsOnUpdate(next) {
var overwrite = this.options.overwrite;
this.update({}, genUpdates(this.getUpdate(), overwrite), {
overwrite: overwrite
});
applyTimestampsToChildren(this);
next();
}
因此,您可以看到所有'pre' 中间件处理程序正在为每个“更新”方法变体和相同的功能代码注册。这些都实质上修改了您发出的任何“更新”中的$set 运算符,以包含updatedAt 字段,或者您在架构选项中映射到该键的任何名称。
使用“upsert”操作发送的实际语句使用$setOnInsert 作为createdAt 字段或映射的选项名称(参见清单顶部)。此操作仅在“更新插入”实际发生时适用,因此存在的文档仅与任何“更新”方法相匹配,该值从不实际触及。
这些操作符是 MongoDB 工作方式的一部分,与 mongoose 无关,但此处显示的代码显示了 mongoose 如何“调整”您的“更新”操作以包含这些额外操作。
作为参考 schema.js 中的整个 main 函数,它计算出当前应用的内容从 Line #798 开始,用于 genUpdates() 函数,在此处显示的清单底部调用,但顶部是最后几个该函数的行,其中$setOnInsert 的键被定义。
因此,总而言之,是的,每个“更新”操作都是有意为 updatedAt 映射字段分配了当前的 Date 值,并且“更新”被修改为包含 $setOnInsert 操作 仅适用于由于 createdAt 映射字段的“更新插入”操作而创建新文档时。