Eigentlich, aber für die Tatsache, dass Mongoose tatsächlich unter der Decke mit dem Update "herumspielt", ist dies tatsächlich die Standardaktion Ihrer Übermittlung an eine reguläre MongoDB-Funktion.
Mongoose hält es daher für „klug“, bequem davon auszugehen, dass Sie ein $set
ausgeben wollten Anleitung hier. Da Sie das in diesem Fall eigentlich nicht wollen, schalten Sie dieses Verhalten per { overwrite: true }
aus in den Optionen, die an .update()
übergeben werden Methode:
Als vollständiges Beispiel:
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();
}
})()
Erzeugt:
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"
}
Das Anzeigen des Dokuments wird "überschrieben", da wir den $set
unterdrückt haben Operation, die sonst interpoliert worden wäre. Die beiden Beispiele werden zuerst ohne overwrite
angezeigt Option, die den $set
anwendet Modifikator, und dann "mit" dem overwrite
Option, bei der das Objekt, das Sie für das "Update" übergeben haben, berücksichtigt wird und kein solches $set
Modifikator wird angewendet.
Beachten Sie, dass der MongoDB-Knotentreiber dies "standardmäßig" so macht. Also das Verhalten beim Hinzufügen des "impliziten" $set
wird von Mongoose ausgeführt, es sei denn, Sie sagen ihm, dass er es nicht tun soll.
HINWEIS Der wahre Weg zum "Ersetzen" wäre tatsächlich die Verwendung von replaceOne
, entweder als API-Methode von replaceOne()
oder durch bulkWrite()
. Das overwrite
ist ein Erbe davon, wie Mongoose $set
anwenden möchte wie oben beschrieben und demonstriert, jedoch führt die offizielle API von MongoDB replaceOne
ein als "besonderes" König von update()
Vorgang, der nicht erlaubt ist die Verwendung von atomaren Operatoren wie $set
innerhalb der Anweisung und schlägt fehl, wenn Sie es versuchen.
Dies ist seit replace semantisch viel klarer liest sich sehr deutlich, wofür die Methode eigentlich verwendet wird. Innerhalb von Standard-API-Aufrufen an update()
Varianten erlauben es Ihnen natürlich immer noch, die atomaren Operatoren wegzulassen und werden nur ersetzen Inhalt sowieso. Aber Warnungen sollten erwartet werden.