sql >> Database >  >> NoSQL >> MongoDB

Mongoose overschrijft het document in plaats van `$set` velden

Eigenlijk, maar voor het feit dat mangoest eigenlijk "rotzooit" met de update onder de dekens, is dit eigenlijk de standaardactie van je onderwerping aan een reguliere MongoDB-functie.

Dus mangoest vindt het "verstandig" als een gemakkelijke methode om te "veronderstellen" dat je een $set wilde uitgeven instructie hier. Aangezien je dat in dit geval eigenlijk niet wilt, zet je dat gedrag uit via { overwrite: true } in de opties doorgegeven aan een .update() methode:

Als volledig voorbeeld:

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();
  }

})()

Produceert:

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"
}

De weergave van het document is "overschreven" omdat we de $set . hebben onderdrukt bewerking die anders geïnterpoleerd zou zijn. De twee voorbeelden worden eerst weergegeven zonder de overwrite optie, die de $set . toepast modifier, en dan "met" de overwrite optie, waarbij het object dat je hebt doorgegeven voor de "update" wordt gerespecteerd en niet zo'n $set modifier is toegepast.

Let op, dit is hoe het MongoDB Node-stuurprogramma dit "standaard" doet. Dus het gedrag van het toevoegen in de "impliciete" $set wordt gedaan door mangoest, tenzij je zegt dat het niet moet.

OPMERKING De echte manier om te "vervangen" zou eigenlijk zijn om replaceOne . te gebruiken , ofwel als de API-methode van replaceOne() of via bulkWrite() . De overwrite is een erfenis van hoe mangoest $set wil toepassen zoals hierboven beschreven en gedemonstreerd, maar de MongoDB officiële API introduceert replaceOne als een "special" koning van update() bewerking die niet toestaat het gebruik van atomaire operatoren zoals $set binnen de instructie en zal een foutmelding geven als je het probeert.

Dit is semantisch veel duidelijker sinds vervangen leest heel duidelijk waar de methode eigenlijk voor wordt gebruikt. Binnen standaard API-aanroepen naar de update() varianten laten je natuurlijk nog steeds de atomaire operatoren weglaten en zullen gewoon vervangen inhoud toch. Maar waarschuwingen zijn te verwachten.



  1. mongodb:de hoogste numerieke waarde van een kolom vinden

  2. Hoe maak je een lijst van alle MongoDB-databases in Node.js?

  3. Hoe een bulkupdate van documenten in MongoDB met Java uitvoeren?

  4. MongoDB-aggregatieprojecttekenreeks naar ObjectId