MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Mongoose nadpisuje dokument zamiast pól `$set`

Właściwie, ale ze względu na fakt, że mangusta faktycznie "bałagani" z aktualizacją pod okładkami, jest to w rzeczywistości domyślna akcja przesyłania do zwykłej funkcji MongoDB.

Tak więc mangusta uważa, że ​​„mądre” jako wygodna metoda „przypuszczania”, że zamierzasz wydać $set instrukcja tutaj. Ponieważ właściwie nie chcesz tego robić w tym przypadku, wyłącz to zachowanie za pomocą { overwrite: true } w opcjach przekazanych do dowolnego .update() metoda:

Jako pełny przykład:

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

})()

Produkuje:

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

Pokazuje, że dokument jest „nadpisany”, ponieważ pominięto $set operacja, która w innym przypadku zostałaby interpolowana. Dwie próbki pokazują się jako pierwsze bez overwrite opcja, która stosuje $set modyfikator, a następnie "z" overwrite opcja, w której obiekt, który przekazałeś do "aktualizacji" jest respektowany i nie ma takiego $set zastosowano modyfikator.

Zauważ, że w ten sposób sterownik MongoDB Node robi to "domyślnie". Tak więc zachowanie polegające na dodawaniu „niejawnego” $set jest robiony przez mangusty, chyba że powiesz mu, żeby tego nie robił.

UWAGA Prawdziwym sposobem na „zastąpienie” byłoby użycie replaceOne , jako metoda API funkcji replaceOne() lub przez bulkWrite() . overwrite jest spuścizną tego, jak mangusta chce zastosować $set jak opisano i zademonstrowano powyżej, jednak oficjalny interfejs API MongoDB wprowadza replaceOne jako „specjalny” król update() operacja, która nie pozwala użycie operatorów atomowych, takich jak $set w oświadczeniu i popełni błąd, jeśli spróbujesz.

Jest to znacznie jaśniejsze semantycznie, ponieważ zamień czyta bardzo wyraźnie, do czego faktycznie służy ta metoda. W ramach standardowych wywołań API do update() warianty oczywiście nadal pozwalają pominąć operatory atomowe i po prostu zastąpią treść mimo wszystko. Ale należy się spodziewać ostrzeżeń.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak mogę wysłać zapytanie do mongodb za pomocą mongoid/rails bez przekroczenia limitu czasu?

  2. Jak zainstalować wcześniejszą wersję mongodb z homebrew?

  3. Jak używać Spring do łączenia się z MongoDB, która wymaga uwierzytelnienia?

  4. Czy należy włączyć księgowanie MongoDB?

  5. Jak używać modyfikatora aktualizacji $push w MongoDB i C# podczas aktualizowania tablicy w dokumencie?