实际上,实际上,猫鼬实际上是在“掩盖”更新下的事实,这实际上是您提交给常规MongoDB函数的默认操作。
因此,猫鼬认为它是“明智的”,作为一种方便的方法来“假设”你在这里发布$set
指令。
作为一个完整的例子:
const mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
mongoose.set('debug',true);
const uri = 'mongodb://localhost/test',
options = { useMongoClient: true };
const testSchema = new Schema({
name: String,
phone: String
});
const Test = mongoose.model('Test', testSchema);
function log(data) {
console.log(JSON.stringify(data,undefined,2))
}
(async function() {
try {
const conn = await mongoose.connect(uri,options);
// Clean data
await Promise.all(
Object.keys(conn.models).map(m => conn.models[m].remove({}))
);
// Create a document
let test = await Test.create({
name: 'john doe',
phone: '+12345678901'
});
log(test);
// This update will apply using $set for the name
let notover = await Test.findOneAndUpdate(
{ _id: test._id },
{ name: 'Bill S. Preston' },
{ new: true }
);
log(notover);
// This update will just use the supplied object, and overwrite
let updated = await Test.findOneAndUpdate(
{ _id: test._id },
{ name: 'Dan Smith' },
{ new: true, overwrite: true }
);
log(updated);
} catch (e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})()
产地:
因为你其实并不想这样做,在这种情况下,你传递给任何
.update()
方法的选项通过
{ overwrite: true }
关闭该行为
Mongoose: tests.remove({}, {})
Mongoose: tests.insert({ name: 'john doe', phone: '+12345678901', _id: ObjectId("596efb0ec941ff0ec319ac1e"), __v: 0 })
{
"__v": 0,
"name": "john doe",
"phone": "+12345678901",
"_id": "596efb0ec941ff0ec319ac1e"
}
Mongoose: tests.findAndModify({ _id: ObjectId("596efb0ec941ff0ec319ac1e") }, [], { '$set': { name: 'Bill S. Preston' } }, { new: true, upsert: false, remove: false, fields: {} })
{
"_id": "596efb0ec941ff0ec319ac1e",
"name": "Bill S. Preston",
"phone": "+12345678901",
"__v": 0
}
Mongoose: tests.findAndModify({ _id: ObjectId("596efb0ec941ff0ec319ac1e") }, [], { name: 'Dan Smith' }, { new: true, overwrite: true, upsert: false, remove: false, fields: {} })
{
"_id": "596efb0ec941ff0ec319ac1e",
"name": "Dan Smith"
}
显示文档被“覆盖”,因为我们抑制了$set
操作,否则该操作将被插入。这两个示例首先显示overwrite
选项,其中应用了$set
修饰符,然后“with”overwrite
选项,其中您传入“更新”的对象受到尊重,并且没有应用此修饰符。
请注意,这是MongoDB节点驱动程序如何“默认”执行此操作。所以在“隐式”$set
中加入的行为是通过猫鼬来完成的,除非你不告诉它。
您是否尝试使用更新函数(而不是findOneAndUpdate)? –
@ israel.zinc我有,没有区别 – stkvtflw
@ israel.zinc它不会有所作为。这是通过在[更新对象]中添加['$ set'](https://docs.mongodb.com/manual/reference/operator/update/set/)来做到这一点的“猫鼬”,标准驱动程序只需要通过“按原样”传递该对象。所以这种行为需要为猫鼬“关闭”,以便使它像你实际要求的那样工作。 –