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

(mongoose/løfter) Hvordan kontrollerer du, om dokumentet er oprettet ved hjælp af findOneAndUpdate med upsert

I tilfælde af .findOneAndUpdate() eller nogen af ​​.findAndModify() kernedrivervarianter for mongoose, den faktiske tilbagekaldssignatur har "tre" argumenter:

 function(err,result,raw)

Den første er ethvert fejlsvar, derefter det ændrede eller originale dokument afhængigt af muligheder og det tredje, som er et skriveresultat af den udstedte erklæring.

Det tredje argument skulle returnere data meget som dette:

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

Med det konsistente felt derinde som lastErrorObject.updatedExisting være enten true/false afhængig af resultatet af, om der opstod en opstyrtning. Bemærk, at der også er en "opsat" værdi, der indeholder _id svar for det nye dokument, når denne egenskab er false , men ikke når det er true .

Som sådan vil du så ændre din håndtering for at overveje den tredje betingelse, men dette virker kun med et tilbagekald og ikke et løfte:

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

Hvor jeg også kraftigt vil anbefale dig at bruge opdateringsoperatører snarere end råobjekter her, da et råobjekt altid vil overskrive hele dokumentet, men alligevel vil operatører som $set bare påvirke de angivne felter.

Bemærk også, at alle matchende "forespørgselsargumenter" til sætningen automatisk tildeles i det nye dokument, så længe deres værdi er et nøjagtigt match, der ikke blev fundet.

I betragtning af at brugen af ​​et løfte ikke ser ud til at returnere de yderligere oplysninger af en eller anden grund, så kan du ikke se, hvordan dette er muligt med et løfte andet end at indstille { new: false} og dybest set, når der ikke returneres noget dokument, så er det et nyt.

Du har alle de dokumentdata, der forventes at blive indsat alligevel, så det er ikke sådan, at du virkelig har brug for disse data returneret alligevel. Det er i virkeligheden, hvordan de native driver-metoder håndterer dette i kernen, og kun reagerer med den "upserted" _id værdi, når der opstår en upsert.

Dette kommer virkelig ned til et andet emne, der diskuteres på dette websted, under:

Kan løfter have flere argumenter til at blive opfyldt?

Hvor dette virkelig kommer ned til opløsningen af ​​flere objekter i et løftesvar, hvilket er noget, der ikke direkte understøttes i den oprindelige specifikation, men der er fremgangsmåder anført der.

Så hvis du implementerer Bluebird-løfter og bruger .spread() metode der, så er alt i orden:

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

Hvilket selvfølgelig returnerer begge objekter og du kan få adgang derefter konsekvent:

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

Her er en komplet liste, der viser den normale adfærd:

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

For en ordens skyld har den oprindelige driver ikke selv dette problem, da svarobjektet faktisk er det eneste objekt, der returneres bortset fra enhver fejl:

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

Så det er altid sådan noget her:

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


  1. Tilfældig sorteringsrækkefølge

  2. Hvordan får man printoutput til fejlfinding af kort/reducer i Mongoid?

  3. Hvordan kan jeg importere data til Mongodb fra Json-fil ved hjælp af java

  4. Hvordan fungerer ServiceStack PooledRedisClientManager failover?