MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB Node.js nativer Treiber schluckt stillschweigend die `bulkWrite`-Ausnahme

Also wie kommentiert:"Es ist ein Fehler". Genauer gesagt ist der Fehler genau hier :

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

Das Problem ist, dass die "Antwort" (oder r ) im Callback, der in ein Promise eingeschlossen wird ist nicht wirklich null , und daher ist die Bedingung trotz Vorliegens des Fehlers nicht true und reject(err) nicht aufgerufen wird, sondern resolve(r) gesendet wird und daher nicht als Ausnahme betrachtet wird.

Das Korrigieren würde einige Triage erfordern, aber Sie können entweder wie erwähnt "umgehen", indem Sie die writeErrors untersuchen -Eigenschaft in der Antwort vom aktuellen bulkWrite() Implementierung oder betrachten Sie eine der anderen Alternativen als:

Direkte Verwendung der Bulk-API-Methoden:

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

})();

Völlig in Ordnung, hat aber natürlich das Problem, dass bei Serverimplementierungen ohne Bulk-API-Unterstützung nicht auf natürliche Weise auf die Verwendung der Legacy-API-Methoden zurückgegriffen werden muss.

Versprechen manuell verpacken

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

})();

Wie bereits erwähnt, liegt das Problem in der Implementierung von bulkWrite() kommt als Promise zurück . Stattdessen können Sie mit callback() codieren Formular aus und geben Sie Ihr eigenes Promise ab Verpackung, um sich so zu verhalten, wie Sie es erwarten.

Wie bereits erwähnt, sind ein JIRA-Problem und Triage erforderlich, um die Ausnahmen richtig zu behandeln. Wird aber hoffentlich bald behoben. Wählen Sie in der Zwischenzeit einen Ansatz von oben.