sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB Node.js inbyggda drivrutin sväljer tyst "bulkWrite"-undantaget

Så som kommenterat, "Det är en bugg". Specifikt är felet här :

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

Problemet är att "svaret" ( eller r ) i återuppringningen som lindas in i ett Promise är faktiskt inte null , och trots att felet finns är villkoret därför inte true och reject(err) anropas inte, utan snarare resolve(r) skickas och därför anses detta inte vara ett undantag.

Att korrigera skulle kräva en del triage, men du kan antingen "lösa" som nämnts genom att inspektera writeErrors egenskapen i svaret från den aktuella bulkWrite() implementering eller överväg ett av de andra alternativen som:

Använda Bulk API-metoderna direkt:

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

})();

Helt ok men har naturligtvis problemet med att inte naturligt gå tillbaka på serverimplementeringar utan Bulk API-stöd till att istället använda de äldre API-metoderna.

Slå in löftet manuellt

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

})();

Som nämnts ligger problemet i implementeringen av hur bulkWrite() återkommer som ett Promise . Så istället kan du koda med callback() formulär och gör ditt eget Promise inpackning för att agera som du förväntar dig.

Återigen, som nämnt, behöver ett JIRA-problem och triage som är det korrekta sättet att hantera undantagen. Men förhoppningsvis löser sig snart. Under tiden, välj ett tillvägagångssätt från ovan.




  1. TTL för en uppsättningsmedlem

  2. Hur man återanvänder mongodb-anslutning genom Promise

  3. Första stegen med Redis

  4. Json.NET som avserialiserar Mongo ObjectId ger fel resultat