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

Il driver nativo MongoDB Node.js ingoia silenziosamente l'eccezione "bulkWrite".

Quindi, come commentato, "È un bug". In particolare il bug è proprio qui :

 // Return a Promise
  return new this.s.promiseLibrary(function(resolve, reject) {
    bulkWrite(self, operations, options, function(err, r) {
      if(err && r == null) return reject(err);
      resolve(r);
    });
  });

Il problema è che la "risposta" ( o r ) nella callback che viene racchiusa in una Promise in realtà non è null , e quindi nonostante l'errore sia presente la condizione non è quindi true e reject(err) non viene chiamato, ma piuttosto il resolve(r) viene inviato e quindi questa non è considerata un'eccezione.

La correzione richiederebbe un po' di valutazione, ma puoi 'ovviare' come menzionato ispezionando writeErrors proprietà nella risposta dall'attuale bulkWrite() implementazione o considerare una delle altre alternative come:

Utilizzando direttamente i metodi dell'API Bulk:

const MongoClient = require('mongodb').MongoClient,
      uri  = 'mongodb://localhost:27017/myNewDb';

(async () => {

  let db;

  try {

    db = await MongoClient.connect(uri);

    let bulk = db.collection('myNewCollection').initializeOrderedBulkOp();

    bulk.find({ foo: 'bar' }).upsert().updateOne({
      $setOnInsert: { count: 0 },
      $inc: { count: 0 }
    });

    let result = await bulk.execute();
    console.log(JSON.stringify(result,undefined,2));

  } catch(e) {
    console.error(e);
  } finally {
    db.close();
  }

})();

Perfettamente a posto, ma ovviamente ha il problema di non regredire naturalmente sulle implementazioni del server senza il supporto dell'API in blocco per utilizzare invece i metodi dell'API legacy.

Confezione manuale della promessa

(async () => {

  let db = await require('mongodb').MongoClient.connect('mongodb://localhost:27017/myNewDb');

  let mongoOps = [{
    updateOne: {
      filter: { foo: "bar" },
      update: {
        $setOnInsert: { count:0 },
        $inc: { count:1 },
      },
      upsert: true,
    }
  }];

  try {
    let result = await new Promise((resolve,reject) => {

      db.collection("myNewCollection").bulkWrite(mongoOps, (err,r) => {
        if (err) reject(err);
        resolve(r);
      });
    });
    console.log(JSON.stringify(result,undefined,2));
    console.log("Success!");
  } catch(e) {
    console.log("Failed:");
    console.log(e);
  }

})();

Come notato, il problema risiede nell'implementazione di come bulkWrite() sta tornando come una Promise . Quindi puoi invece programmare con il callback() forma e fai la tua Promise avvolgere per agire come ti aspetti.

Anche in questo caso, come notato, è necessario un problema JIRA e un Triage in cui è il modo corretto di gestire le eccezioni. Ma speriamo si risolva presto. Nel frattempo, scegli un approccio dall'alto.