考虑这个命令:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, function(err) {
...
})
与此相对:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, { '$set': updateObj }, function(err) {
...
})
在开发我的项目时,我惊讶地发现第一个命令的结果与第二个命令的结果相同:updateObj
被合并到数据库中的现有记录中,即使在它应该替换它的第一种情况。这是mongoose / mongodb中的错误还是我做错了什么?如何在更新时替换对象而不是合并它?我使用的是mongoose 4.0.7。
感谢。
==========
更新
这是实际的WorkPlan架构定义:
workPlanSchema = mongoose.Schema({
planId: { type: String, required: true },
projectName: { type: String, required: true },
projectNumber: { type: String, required: false },
projectManagerName: { type: String, required: true },
clientPhoneNumber: { type: String, required: false },
clientEmail: { type: String, required: true },
projectEndShowDate: { type: Date, required: true },
segmentationsToDisplay: { type: [String], required: false },
areas: [
{
fatherArea: { type: mongoose.Schema.ObjectId, ref: 'Area' },
childAreas: [{ childId : { type: mongoose.Schema.ObjectId, ref: 'Area' }, status: { type: String, default: 'none' } }]
}
],
logoPositions: [
{
lat: { type: Number, required: true },
lng: { type: Number, required: true }
}
],
logoPath: { type: String, required: false },
}, { collection: 'workPlans' });
WorkPlan = mongoose.model('WorkPlan', workPlanSchema);
这是updateObj
的一个例子:
var updateObj = {
projectManagerName: projectManagerName,
clientEmail: clientEmail,
clientPhoneNumber: clientPhoneNumber,
segmentationsToDisplay: segmentationsToDisplay ? segmentationsToDisplay.split(',') : []
}
因此,当我没有使用$ set标志时,我希望字段projectNumber
例如不存在于新记录中,但我发现它仍然存在。
答案 0 :(得分:6)
Mongoose更新会将所有顶级密钥视为$set
操作(在较旧的文档中更明确:Mongoose 2.7.x update docs)。
为了获得您想要的行为,您需要将overwrite
选项设置为true:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, { overwrite: true }, function(err) {
...
})
答案 1 :(得分:0)
除了以上答案:
[options.overwrite = false]«Boolean»默认情况下,如果不包括 任何文档中的更新运算符,Mongoose都会为您将文档包装在$ set中。 这样可以防止您意外覆盖文档。这个 选项告诉猫鼬跳过添加$ set。
链接到文档:https://mongoosejs.com/docs/api.html#model_Model.update