sql >> Base de Datos >  >> NoSQL >> MongoDB

El controlador nativo de MongoDB Node.js traga silenciosamente la excepción `bulkWrite`

Entonces, como comentó, "Es un error". Específicamente, el error está aquí mismo :

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

El problema es que la "respuesta" (o r ) en la devolución de llamada que se envuelve en una Promise en realidad no es null y, por lo tanto, a pesar de que el error está presente, la condición no es true y reject(err) no se llama, sino el resolve(r) se está enviando y, por lo tanto, esto no se considera una excepción.

La corrección necesitaría un poco de clasificación, pero puede 'trabajar' como se mencionó al inspeccionar los writeErrors propiedad en la respuesta del bulkWrite() actual implementación o considerar una de las otras alternativas como:

Utilizando los métodos de la API masiva directamente:

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

})();

Perfectamente bien, pero por supuesto tiene el problema de no retroceder naturalmente en las implementaciones del servidor sin soporte de API masiva para usar los métodos API heredados en su lugar.

Envolver la promesa manualmente

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

})();

Como se señaló, el problema radica en la implementación de cómo bulkWrite() regresa como una Promise . Entonces, en su lugar, puede codificar con callback() formulario y haz tu propia Promise envolver para actuar como esperas que lo haga.

Nuevamente, como se señaló, necesita un problema de JIRA y una clasificación para cuál es la forma correcta de manejar las excepciones. Pero esperemos que se resuelva pronto. Mientras tanto, elige un enfoque desde arriba.