下面的脚本在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.system.profile.find({})
审核db.setProfileLevel(2)
,我们可以看到异常:
{
"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" : ""
}
为什么司机吞下这样的错误?我看起来肯定是一个错误,但我想我先问这里只是为了确定。
答案 0 :(得分:2)
所以评论,"它是一个错误"。具体来说,错误是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
和{ {1}}未被调用,而是reject(err)
正在被发送,因此这不被视为例外。
纠正需要一些分类,但你可以“解决”问题。通过检查当前resolve(r)
实现的响应中的writeErrors
属性或者考虑其他替代方案之一来提及:
bulkWrite()
非常好但当然还有一个问题,即如果没有Bulk API支持使用旧版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();
}
})();
如上所述,问题在于(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()
换行,以便按照您的预期行事。
再次如上所述,需要一个JIRA问题和Triage,这是处理异常的正确方法。但希望很快得到解决。与此同时,从上面选择一种方法。