Mongoose Schema:
new Schema({
...
createDate: { type: Date, default: Date.now },
updateDate: { type: Date, default: Date.now }
});
Upsert操作:
const upsertDoc = {
...
}
Model.update({ key: 123 }, upsertDoc, { upsert: true })
当我使用update
或findOneAndUpdate
进行插播时,无论是插入还是更新文档,都会更新默认架构值createDate
和updateDate
。当我使用$set
时(当然我没有传递日期)也是如此。
我似乎没有找到任何可以告诉它是否是预期的行为。除非明确设置,否则我希望仅在插入时添加日期而不更新日期。
答案 0 :(得分:1)
好吧,我始终建议您使用提供的和推荐的方式通过mongoose管理createdAt
和updatedAt
。只需将timeStamp: true
作为架构选项传递即可。
这始终是最佳做法,让您不必担心此类行为。
我使用它,我从未发现使用update
或findOneAndUpdate
的时间戳问题。
以下是您使用它的方式
new Schema({
... //Your schema
},{ timestamps: true})
答案 1 :(得分:1)
如果您正在寻找预期行为的“证据”,那么请查看源代码本身。特别是在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
字段或映射选项名称(请参阅列表顶部)。当“upsert”实际发生时,此操作仅适用,因此存在且仅与任何“更新”方法匹配的文档从不实际触及此值。
这些运算符是MongoDB如何工作的一部分而不是与mongoose有关,但此处显示的代码显示了猫鼬如何“调整”您的“更新”操作以包含这些额外的操作。
作为参考,schema.js
中用于解决当前应用内容的整个主要功能始于Line #798 genUpdates()
函数,如此处所示的清单底部所示, top部分是该函数的最后几行,其中$setOnInsert
的键被定义。
总而言之,每个“更新”操作都是有意的,updatedAt
映射字段已分配当前Date
值,并且“更新”被修改为包含{{3当作为createdAt
映射字段的“upsert”操作的结果创建新文档时,仅应用的操作。