MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Mongoose презаписва документа, а не `$set` полета

Всъщност, с изключение на факта, че mongoose всъщност "забърква" с актуализацията под завивките, това всъщност е действието по подразбиране при изпращането ви на обикновена функция на MongoDB.

Така че mongoose смята, че е "мъдро" като удобен метод да "предполагаме", че сте имали предвид да издадете $set инструкция тук. Тъй като всъщност не искате да правите това в този случай, изключвате това поведение чрез { overwrite: true } в опциите, предадени на всеки .update() метод:

Като пълен пример:

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

})()

Произвежда:

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

Показването на документа е "презаписано", защото потиснахме $set операция, която иначе би била интерполирана. Двете проби се показват първи без overwrite опция, която прилага $set модификатор, а след това "с" overwrite опция, където обектът, който сте предали за "актуализация", се спазва и няма такъв $set се прилага модификатор.

Забележете, така драйверът на MongoDB Node прави това "по подразбиране". Така че поведението на добавяне в "неявния" $set се извършва от мангуста, освен ако не му кажете да не го прави.

ЗАБЕЛЕЖКА Истинският начин за „замяна“ всъщност би бил да използвате replaceOne , или като API метод на replaceOne() или чрез bulkWrite() . overwrite е наследство на начина, по който mongoose иска да приложи $set както е описано и демонстрирано по-горе, обаче официалният API на MongoDB въвежда replaceOne като „специален“ крал на update() операция, коятоне позволявата използването на атомни оператори като $set в изявлението и ще грешка, ако опитате.

Това е много по-ясно семантично, тъй като замени чете много ясно за какво всъщност се използва методът. В рамките на стандартните API извиквания към update() вариантите, разбира се, все още ви позволяват да пропуснете атомните оператори и просто ще заменят съдържание така или иначе. Но трябва да се очакват предупреждения.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Мониторинг и защита на MongoDB с ClusterControl Advisors

  2. Как да управлявате бази данни и колекции в MongoDB

  3. Как да изравнявам поддокумент на основно ниво в MongoDB?

  4. MongoDB и PostgreSQL мисли

  5. Накарайте Spark, Python и MongoDB да работят заедно