MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

(luwak/janji) Bagaimana Anda memeriksa apakah dokumen dibuat menggunakan findOneAndUpdate dengan upsert

Dalam kasus .findOneAndUpdate() atau salah satu dari .findAndModify() varian driver inti untuk luwak, tanda tangan panggilan balik yang sebenarnya memiliki argumen "tiga":

 function(err,result,raw)

Dengan yang pertama adalah respon kesalahan, kemudian dokumen yang dimodifikasi atau asli tergantung pada opsi dan yang ketiga adalah hasil tulis dari pernyataan yang dikeluarkan.

Argumen ketiga itu seharusnya mengembalikan data seperti ini:

{ lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 55e12c65f6044f57c8e09a46 },
  value: { _id: 55e12c65f6044f57c8e09a46, 
           number: 55555555, 
           country: 'US', 
           token: "XXX", 
           appInstalled: true,
           __v: 0 },
  ok: 1 }

Dengan bidang yang konsisten di sana sebagai lastErrorObject.updatedExisting menjadi true/false tergantung pada hasil apakah upsert terjadi. Perhatikan bahwa ada juga nilai "terbalik" yang berisi _id respons untuk dokumen baru ketika properti ini false , tetapi tidak jika true .

Dengan demikian, Anda kemudian akan memodifikasi penanganan Anda untuk mempertimbangkan kondisi ketiga, tetapi ini hanya berfungsi dengan panggilan balik dan bukan janji:

Inbox.model.findOneAndUpdate(
    { "number": req.phone.number },
    { 
      "$set": {
          "country": req.phone.country,
          "token": hat(),
          "appInstalled": true
      }
    }, 
    { "new": true, "upsert": true },
    function(err,doc,raw) {

      if ( !raw.lastErrorObject.updatedExitsing ) {
         // do things with the new document created
      }
    }
);

Di mana saya juga sangat menyarankan Anda menggunakan operator pembaruan daripada objek mentah di sini, karena objek mentah akan selalu menimpa seluruh dokumen, namun operator seperti $set hanya mempengaruhi bidang yang terdaftar.

Perhatikan juga bahwa setiap "argumen kueri" yang cocok dengan pernyataan akan secara otomatis ditetapkan dalam dokumen baru selama nilainya sama persis dengan yang tidak ditemukan.

Mengingat bahwa menggunakan janji tampaknya tidak mengembalikan informasi tambahan untuk beberapa alasan, maka jangan melihat bagaimana ini mungkin dengan janji selain pengaturan { new: false} dan pada dasarnya ketika tidak ada dokumen yang dikembalikan maka itu adalah dokumen baru.

Anda memiliki semua data dokumen yang diharapkan untuk dimasukkan, jadi Anda tidak benar-benar membutuhkan data itu dikembalikan. Faktanya adalah bagaimana metode driver asli menangani ini pada intinya, dan hanya merespons dengan _id yang "dimasukkan" nilai saat upser terjadi.

Ini benar-benar bermuara pada masalah lain yang dibahas di situs ini, di bawah:

Dapatkah janji memiliki banyak argumen untuk onFulfilled?

Di mana ini benar-benar bermuara pada resolusi beberapa objek dalam respons janji, yang merupakan sesuatu yang tidak didukung secara langsung dalam spesifikasi asli tetapi ada pendekatan yang tercantum di sana.

Jadi, jika Anda mengimplementasikan janji Bluebird dan menggunakan .spread() metode di sana, maka semuanya baik-baik saja:

var async = require('async'),
    Promise = require('bluebird'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var testSchema = new Schema({
  name: String
});

var Test = mongoose.model('Test',testSchema,'test');
Promise.promisifyAll(Test);
Promise.promisifyAll(Test.prototype);

async.series(
  [
    function(callback) {
      Test.remove({},callback);
    },
    function(callback) {
      var promise = Test.findOneAndUpdateAsync(
        { "name": "Bill" },
        { "$set": { "name": "Bill" } },
        { "new": true, "upsert": true }
      );

      promise.spread(function(doc,raw) {
        console.log(doc);
        console.log(raw);
        if ( !raw.lastErrorObject.updatedExisting ) {
          console.log( "new document" );
        }
        callback();
      });
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

Yang tentu saja mengembalikan kedua objek dan Anda dapat mengaksesnya secara konsisten:

{ _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __v: 0 }
{ lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 55e14b7af6044f57c8e09a4e },
  value: { _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __v: 0 },
  ok: 1 }

Berikut adalah daftar lengkap yang menunjukkan perilaku normal:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var testSchema = new Schema({
  name: String
});

var Test = mongoose.model('Test',testSchema,'test');

async.series(
  [
    function(callback) {
      Test.remove({},callback);
    },
    function(callback) {
      Test.findOneAndUpdate(
        { "name": "Bill" },
        { "$set": { "name": "Bill" } },
        { "new": true, "upsert": true }
      ).then(function(doc,raw) {
        console.log(doc);
        console.log(raw);
        if ( !raw.lastErrorObject.updatedExisting ) {
          console.log( "new document" );
        }
        callback();
      });
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

Sebagai catatan, driver asli itu sendiri tidak memiliki masalah ini karena objek respons sebenarnya hanyalah objek yang dikembalikan selain dari kesalahan apa pun:

var async = require('async'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient;

MongoClient.connect('mongodb://localhost/test',function(err,db) {

  var collection = db.collection('test');

  collection.findOneAndUpdate(
    { "name": "Bill" },
    { "$set": { "name": "Bill" } },
    { "upsert": true, "returnOriginal": false }
  ).then(function(response) {
    console.log(response);
  });
});

Jadi selalu seperti ini:

{ lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 55e13bcbf6044f57c8e09a4b },
  value: { _id: 55e13bcbf6044f57c8e09a4b, name: 'Bill' },
  ok: 1 }


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Kesalahan audit mongodb booting musim semi

  2. bagaimana cara melepaskan caching yang digunakan oleh Mongodb?

  3. Bisakah mongorestore mengambil argumen url tunggal alih-alih argumen terpisah?

  4. membuat grup dan menganalisis data dari daftar array di lahir

  5. Mongodb dapat membuang tetapi tidak menyimpan kesalahan yang memulihkan dari <db-name.bson> sisipan terlalu besar