Sebenarnya, tetapi fakta bahwa luwak sebenarnya "mengacaukan" pembaruan di balik sampul, ini sebenarnya adalah tindakan default dari pengiriman Anda ke fungsi MongoDB biasa.
Jadi luwak menganggapnya "bijaksana" sebagai metode mudah untuk "menganggap" Anda bermaksud mengeluarkan $set
instruksi di sini. Karena Anda sebenarnya tidak ingin melakukan itu dalam kasus ini, Anda mematikan perilaku itu melalui { overwrite: true }
dalam opsi yang diteruskan ke .update()
any metode:
Sebagai contoh lengkap:
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();
}
})()
Menghasilkan:
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"
}
Menampilkan dokumen "ditimpa" karena kami menekan $set
operasi yang sebaliknya akan diinterpolasi. Kedua sampel ditampilkan terlebih dahulu tanpa overwrite
opsi, yang menerapkan $set
pengubah, lalu "dengan" overwrite
opsi, di mana objek yang Anda berikan untuk "pembaruan" dihormati dan tidak ada $set
. seperti itu pengubah diterapkan.
Catatan, ini adalah bagaimana driver MongoDB Node melakukan ini "secara default". Jadi perilaku menambahkan $set
"implisit" sedang dilakukan oleh luwak, kecuali jika Anda melarangnya.
CATATAN Cara sebenarnya untuk "mengganti" adalah dengan menggunakan
replaceOne
, baik sebagai metode APIreplaceOne()
atau melaluibulkWrite()
.overwrite
adalah warisan bagaimana luwak ingin menerapkan$set
seperti yang dijelaskan dan didemonstrasikan di atas, namun API resmi MongoDB memperkenalkanreplaceOne
sebagai "istimewa" rajaupdate()
operasi yang tidak mengizinkan penggunaan operator atom seperti$set
dalam pernyataan dan akan error jika Anda mencoba.Ini jauh lebih jelas secara semantik sejak ganti membaca dengan sangat jelas untuk apa metode ini sebenarnya digunakan. Dalam panggilan API standar ke
update()
varian tentu saja masih memungkinkan Anda untuk menghilangkan operator atom dan hanya akan mengganti konten pula. Tapi peringatan harus diharapkan.