En fait, à l'exception du fait que la mangouste "s'amuse" en secret avec la mise à jour, il s'agit en fait de l'action par défaut de votre soumission à une fonction MongoDB normale.
Ainsi, la mangouste estime qu'il est "sage", en tant que méthode pratique, de "présumer" que vous vouliez émettre un $set
instruction ici. Puisque vous ne voulez pas faire cela dans ce cas, vous pouvez désactiver ce comportement via { overwrite: true }
dans les options passées à tout .update()
méthode :
A titre d'exemple complet :
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();
}
})()
Produit :
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"
}
Montrer que le document est "écrasé" parce que nous avons supprimé le $set
qui, sinon, aurait été interpolée. Les deux échantillons montrent le premier sans le overwrite
qui applique l'option $set
et ensuite "avec" le modificateur overwrite
où l'objet que vous avez transmis pour la "mise à jour" est respecté et aucun objet de ce type n'est utilisé. $set
est appliqué.
Notez que c'est ainsi que le pilote MongoDB Node procède "par défaut". Ainsi, le comportement de l'ajout de l'élément "implicite" $set
est fait par la mangouste, sauf si vous lui dites de ne pas le faire.
NOTE La véritable façon de "remplacer" serait en fait d'utiliser replaceOne
soit en tant que méthode API de replaceOne()
ou par bulkWrite()
. Le site overwrite
est un héritage de la façon dont la mangouste veut appliquer $set
tel que décrit et démontré ci-dessus, cependant l'API officielle de MongoDB introduit replaceOne
en tant que "spécial" roi de update()
opération qui ne permet pas l'utilisation d'opérateurs atomiques comme $set
à l'intérieur de la déclaration et vous obtiendrez une erreur si vous essayez.
Ceci est beaucoup plus clair sémantiquement puisque remplacer indique très clairement à quoi sert la méthode. Dans les appels standard de l'API à la méthode update()
Les variantes vous permettent bien sûr d'omettre les opérateurs atomiques et se contenteront de remplacer contenu de toute façon. Mais il faut s'attendre à des avertissements.