実際には、しかし、mongooseが実際に内部で更新を「いじっている」という事実のために、これは実際には通常のMongoDB関数への送信のデフォルトのアクションです。
したがって、マングースは、$setを発行することを意図したことを「推定」するための便利な方法として「賢明」であると見なします。 ここでの指示。この場合、実際にはそれを行いたくないので、{ overwrite: true }を介してその動作をオフにします。 .update()に渡されるオプション 方法:
完全な例として:
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();
}
})()
生産物:
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を抑制したため、ドキュメントの表示は「上書き」されます そうでなければ補間されたであろう操作。 2つのサンプルは、最初にoverwriteなしで表示されます $setを適用するオプション 修飾子、次にoverwriteを「使用」します オプション。「更新」のために渡したオブジェクトが尊重され、そのような$setはありません。 修飾子が適用されます。
これは、MongoDBノードドライバーが「デフォルトで」これを行う方法であることに注意してください。したがって、「暗黙の」$setを追加する動作 あなたがそうしないように言わない限り、マングースによって行われています。
注 「置換」する本当の方法は、実際には
replaceOneを使用することです。 、replaceOne()のAPIメソッドとして またはbulkWrite()を介して 。overwriteマングースが$setを適用する方法の遺産です 上記で説明およびデモンストレーションされたように、ただし、MongoDB公式APIはreplaceOneを導入します 「特別」としてupdate()の王様 許可されていない操作$setのようなアトミック演算子の使用法 ステートメント内で、試行するとエラーになります。置換なので、これは意味的にはるかに明確です。 メソッドが実際に何に使用されているかについて非常に明確に読み取ります。
update()への標準API呼び出し内 もちろん、バリアントを使用すると、アトミック演算子を省略でき、置換するだけです。 とにかくコンテンツ。ただし、警告が予想されます。