MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

O driver nativo do MongoDB Node.js engole silenciosamente a exceção `bulkWrite`


Então, como comentado, "É um bug". Especificamente, o bug está bem aqui :
 // 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);
    });
  });

O problema é que a "resposta" ( ou r ) no retorno de chamada que está sendo encapsulado em uma Promise na verdade não é null , e, portanto, apesar do erro estar presente, a condição não é true e reject(err) não está sendo chamado, mas sim o resolve(r) está sendo enviado e, portanto, isso não é considerado uma exceção.

A correção precisaria de alguma triagem, mas você pode 'contornar' conforme mencionado inspecionando os writeErrors propriedade na resposta do bulkWrite() atual implementação ou considerar uma das outras alternativas como:

Usando diretamente os métodos da API em massa:

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

})();

Perfeitamente bem, mas é claro que tem o problema de não regredir naturalmente em implementações de servidor sem suporte de API em massa para usar os métodos de API herdados.

Encaixando a promessa 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);
  }

})();

Conforme observado, o problema está na implementação de como bulkWrite() está retornando como uma Promise . Então você pode codificar com o callback() form e faça sua própria Promise embrulhar para agir como você espera.

Novamente, conforme observado, precisa de um problema e Triagem do JIRA para o qual é a maneira correta de lidar com as exceções. Mas espero que seja resolvido em breve. Enquanto isso, escolha uma abordagem de cima.