sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongoose overskriver dokumentet i stedet for `$set` felter

Faktisk, men for det faktum, at mongoose faktisk "roder med" opdateringen under dynen, er dette faktisk standardhandlingen for din indsendelse til en almindelig MongoDB-funktion.

Så mongoose anser det for "klogt" som en bekvem metode at "formode", at du havde tænkt dig at udstede et $set instruktion her. Da du faktisk ikke ønsker at gøre det i dette tilfælde, slår du den adfærd fra via { overwrite: true } i de muligheder, der er videregivet til enhver .update() metode:

Som et fuldstændigt eksempel:

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

})()

Producerer:

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

Visning af dokumentet er "overskrevet", fordi vi har undertrykt $set operation, der ellers ville være blevet interpoleret. De to eksempler vises først uden overwrite mulighed, som anvender $set modifikator, og derefter "med" overwrite mulighed, hvor det objekt, du sendte til "opdateringen" respekteres, og ingen sådan $set modifikator anvendes.

Bemærk, det er sådan MongoDB Node-driveren gør dette "som standard". Altså adfærden med at tilføje det "implicitte" $set bliver gjort af mongoose, medmindre du fortæller det ikke.

BEMÆRK Den sande måde at "erstatte" på ville faktisk være at bruge replaceOne , enten som API-metoden for replaceOne() eller gennem bulkWrite() . overwrite er en arv af, hvordan mongoose ønsker at anvende $set som beskrevet og demonstreret ovenfor, men MongoDB's officielle API introducerer replaceOne som en "særlig" konge af update() operation, som ikke tillader brugen af ​​atomoperatorer som $set i sætningen og vil fejle, hvis du prøver.

Dette er meget tydeligere semantisk siden erstat læser meget tydeligt på, hvad metoden egentlig bruges til. Inden for standard API-kald til update() varianter giver dig selvfølgelig stadig mulighed for at udelade atomoperatorerne og vil bare erstatte indhold alligevel. Men advarsler bør forventes.



  1. Redis butiksnøgle uden en værdi

  2. Auto-genereret felt til MongoDB ved hjælp af Spring Boot

  3. Rediger rækkefølgen, hvori egenskaber vises i MongoDB

  4. Nye sikkerhedskopierings- og sikkerhedsfunktioner til MySQL og PostgreSQL:ClusterControl Release 1.6.2