gpt4 book ai didi

node.js - MongoDB Node.js原生驱动默默吞下 `bulkWrite`异常

转载 作者:可可西里 更新时间:2023-11-01 09:39:01 26 4
gpt4 key购买 nike

下面的脚本在 mongo bulkWrite op 语法中有一个错误:$setOnInsert: { count:0 }, 是不必要的,因此 mongo 抛出一个异常:“无法更新'count'和'count '同时”。

问题是,node.js 驱动程序似乎没有捕捉到它。此脚本记录“成功!”到控制台。

(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 {
await db.collection("myNewCollection").bulkWrite(mongoOps);
console.log("Success!");
} catch(e) {
console.log("Failed:");
console.log(e);
}

})();

使用 db.setProfileLevel(2) 检查 db.system.profile.find({}) 我们可以看到异常:

{
"op" : "update",
"ns" : "myNewDb.myNewCollection",
"query" : {
"foo" : "bar"
},
"updateobj" : {
"$setOnInsert" : {
"count" : 0
},
"$inc" : {
"count" : 1
}
},
"keyUpdates" : 0,
"writeConflicts" : 0,
"numYield" : 0,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(1),
"w" : NumberLong(1)
}
},
"Database" : {
"acquireCount" : {
"w" : NumberLong(1)
}
},
"Collection" : {
"acquireCount" : {
"w" : NumberLong(1)
}
}
},
"exception" : "Cannot update 'count' and 'count' at the same time",
"exceptionCode" : 16836,
"millis" : 0,
"execStats" : {},
"ts" : ISODate("2017-10-12T01:57:03.008Z"),
"client" : "127.0.0.1",
"allUsers" : [],
"user" : ""
}

为什么驱动程序会吞下这样的错误?我绝对看起来像个错误,但我想我会先在这里问一下以确定。

最佳答案

正如评论所说,“这是一个错误”。具体错误是 right here :

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

问题是回调中的“响应”(或 r )被包装在 Promise 中实际上不是 null ,因此尽管存在错误,但条件不是 true 并且 reject(err) 未被调用,而是 resolve(r) 正在发送,因此这不被视为异常。

更正需要一些分类,但您可以通过检查当前 bulkWrite() 实现的响应中的 writeErrors 属性来“变通”,或者考虑其他选择之一:

直接使用批量 API 方法:

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

})();

非常好,但当然有一个问题,即在没有批量 API 支持的情况下,服务器实现不会自然退化,而是使用旧的 API 方法。

手动包装 Promise

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

})();

如前所述,问题在于 bulkWrite() 如何作为 Promise 返回的实现。因此,您可以使用 callback() 形式进行编码,并进行您自己的 Promise 包装,以便按照您的预期进行操作。

再次如前所述,需要一个 JIRA 问题和分类,这是处理异常的正确方法。但希望尽快得到解决。同时,从上面选择一种方法。

关于node.js - MongoDB Node.js原生驱动默默吞下 `bulkWrite`异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46700461/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com