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

(mangusta/obietnice) Jak sprawdzić, czy dokument został utworzony za pomocą findOneAndUpdate z upsert

W przypadku .findOneAndUpdate() lub dowolny z .findAndModify() podstawowe warianty sterownika dla mangusty, rzeczywista sygnatura wywołania zwrotnego ma „trzy” argumenty:

Funkcja
 function(err,result,raw)

Pierwszym jest dowolna odpowiedź na błąd, następnie zmodyfikowany lub oryginalny dokument w zależności od opcji, a trzeci jest wynikiem zapisu wydanego oświadczenia.

Ten trzeci argument powinien zwracać dane w podobny sposób:

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

Ze spójnym polem tam jako lastErrorObject.updatedExisting będąc true/false w zależności od wyniku tego, czy wystąpiło upsert. Zauważ, że istnieje również „przesunięta” wartość zawierająca _id odpowiedź dla nowego dokumentu, gdy ta właściwość ma wartość false , ale nie wtedy, gdy jest true .

W związku z tym zmodyfikujesz obsługę, aby uwzględnić trzeci warunek, ale działa to tylko z wywołaniem zwrotnym, a nie z obietnicą:

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

W przypadku, gdy sugerowałbym również użycie operatorów aktualizacji zamiast surowych obiektów tutaj, ponieważ surowy obiekt zawsze nadpisze cały dokument, ale operatory takie jak $set wpływa tylko na wymienione pola.

Należy również zauważyć, że wszelkie pasujące „argumenty zapytania” do instrukcji są automatycznie przypisywane w nowym dokumencie, o ile ich wartość jest dokładnym dopasowaniem, które nie zostało znalezione.

Biorąc pod uwagę, że użycie obietnicy z jakiegoś powodu nie zwraca dodatkowych informacji, nie zobacz, jak jest to możliwe z obietnicą inną niż ustawienie { new: false} i w zasadzie, gdy żaden dokument nie zostanie zwrócony, to jest nowy.

Masz wszystkie dane dokumentu, które i tak mają zostać wstawione, więc nie jest tak, że i tak naprawdę potrzebujesz tych danych. W rzeczywistości jest to sposób, w jaki metody natywnego sterownika obsługują to w rdzeniu i odpowiadają tylko za pomocą „przesuniętego” _id wartość, gdy wystąpi upsert.

To naprawdę sprowadza się do innego problemu omawianego na tej stronie, pod:

Czy obietnice mogą mieć wiele argumentów do spełnienia?

Gdzie tak naprawdę sprowadza się to do rozwiązania wielu obiektów w odpowiedzi obietnicy, co nie jest bezpośrednio obsługiwane w natywnej specyfikacji, ale są tam wymienione podejścia.

Więc jeśli zaimplementujesz obietnice Bluebird i użyjesz .spread() metoda tam, to wszystko jest w porządku:

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

Który oczywiście zwraca oba obiekty i możesz uzyskać dostęp do nich konsekwentnie:

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

Oto pełna lista pokazująca normalne zachowanie:

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

Dla przypomnienia, sam sterownik natywny nie ma tego problemu, ponieważ obiekt odpowiedzi jest w rzeczywistości tylko obiektem zwróconym poza jakimkolwiek błędem:

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

Więc zawsze jest mniej więcej tak:

{ 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. Jak określić preferencje odczytu w zapytaniach mongo Meteor

  2. Tablica aktualizacji wewnątrz dokumentu Mongo nie działa

  3. Podstawowe uwagi dotyczące tworzenia kopii zapasowej MongoDB

  4. Lazy loading/więcej przewijania danych w Mongoose/Nodejs

  5. MongoDB $currentDate