- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
好像是 MongoDB insertMany()
将ordered 选项设置为false 的函数可以比ordered 选项设置为true 更有效地插入文档。即使多个文档插入失败,它也可以继续插入文档。
但是我发现没有一种干净的方法可以同时获取每个失败文档的错误和整体命令结果。
(顺便说一句,我使用的是 Node.js 驱动程序 API 2.2。从现在开始我将引用驱动程序的源代码: http://mongodb.github.io/node-mongodb-native/2.2/api/lib_collection.js.html )
首先,如果使用 Promise,则无法同时获取错误和结果。在源代码第 540 行,insertMany()
返回错误或结果 - 不是两者,而 bulkWrite()
回调在源代码第 703 行返回两者。
其次,如果使用回调,事情会变得更糟。当bulkWrite()
调用带有错误和结果的回调函数,insertMany()
使用错误和结果调用回调,但结果是 BulkWrite 的结果,而不是正确转换为 InsertManyResults 的结果。请参阅源代码第 535 行。我认为这是一个错误。
甚至对于 bulkWrite()
, 当错误数为 1 时,它不会将结果正确转换为其格式。请参阅源代码第669行。我认为这也是一个错误。
现在我认为 Node.js 驱动程序根本没有准备好处理这种情况。
目前,似乎没有办法同时正确获取错误和结果。
我对吗?
更新
我运行了一个基于 Neil Lunn 的回答的测试代码。由于我的
Node.js(4.4.5) 不理解 async/await,我不得不用显式的 Promise 重写测试代码。
测试代码如下:
function doTest()
{
var MongoClient = require('mongodb').MongoClient;
var testData = [ 1,2,2,3,3,4,5,6,7,8,9 ];
var db;
return MongoClient.connect('mongodb://127.0.0.1/test')
.then(function (_db)
{
db = _db;
return db.createCollection('test');
})
.then(function ()
{
return db.collection('test').deleteMany({})
.then(function ()
{
return db.collection('test').insertMany(
testData.map(function (_id)
{
return { _id: _id };
}),
{ ordered: false })
.then(function (result)
{
console.log('Promise: result', result);
}, function (err)
{
console.log('Promise: error', err);
});
})
.then(function ()
{
return db.collection('test').deleteMany({});
})
.then(function ()
{
return new Promise(function (resolve, reject)
{
return db.collection('test').insertMany(
testData.map(function (_id)
{
return { _id: _id };
}),
{ ordered: false },
function (err, result)
{
console.log('callback: error', err);
console.log('callback: result', result);
console.log('callback: result.hasWriteErrors', result.hasWriteErrors());
console.log('callback: result.getWriteErrors',
JSON.stringify(result.getWriteErrors(), null, 2));
resolve();
});
});
});
})
.catch(function (err)
{
console.log('catch', err);
})
.then(function ()
{
db.close();
});
}
doTest();
Promise: error { [MongoError: write operation failed]
name: 'MongoError',
message: 'write operation failed',
driver: true,
code: 11000,
writeErrors:
[ { code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] },
{ code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] } ] }
callback: error { [MongoError: write operation failed]
name: 'MongoError',
message: 'write operation failed',
driver: true,
code: 11000,
writeErrors:
[ { code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] },
{ code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] } ] }
callback: result { ok: [Getter],
nInserted: [Getter],
nUpserted: [Getter],
nMatched: [Getter],
nModified: [Getter],
nRemoved: [Getter],
getInsertedIds: [Function],
getUpsertedIds: [Function],
getUpsertedIdAt: [Function],
getRawResponse: [Function],
hasWriteErrors: [Function],
getWriteErrorCount: [Function],
getWriteErrorAt: [Function],
getWriteErrors: [Function],
getLastOp: [Function],
getWriteConcernError: [Function],
toJSON: [Function],
toString: [Function],
isOk: [Function],
insertedCount: 9,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds:
{ '0': 1,
'1': 2,
'2': 2,
'3': 3,
'4': 3,
'5': 4,
'6': 5,
'7': 6,
'8': 7,
'9': 8,
'10': 9 },
n: 9 }
callback: result.hasWriteErrors true
callback: result.getWriteErrors [
{
"code": 11000,
"index": 2,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 2 }",
"op": {
"_id": 2
}
},
{
"code": 11000,
"index": 4,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }",
"op": {
"_id": 3
}
}
]
var testData = [ 1,2,3,3,4,5,6,7,8,9 ];
Promise: error { [MongoError: E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }]
name: 'MongoError',
message: 'E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }',
driver: true,
code: 11000,
index: 3,
errmsg: 'E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }',
getOperation: [Function],
toJSON: [Function],
toString: [Function] }
callback: error { [MongoError: E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }]
name: 'MongoError',
message: 'E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }',
driver: true,
code: 11000,
index: 3,
errmsg: 'E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }',
getOperation: [Function],
toJSON: [Function],
toString: [Function] }
callback: result { ok: [Getter],
nInserted: [Getter],
nUpserted: [Getter],
nMatched: [Getter],
nModified: [Getter],
nRemoved: [Getter],
getInsertedIds: [Function],
getUpsertedIds: [Function],
getUpsertedIdAt: [Function],
getRawResponse: [Function],
hasWriteErrors: [Function],
getWriteErrorCount: [Function],
getWriteErrorAt: [Function],
getWriteErrors: [Function],
getLastOp: [Function],
getWriteConcernError: [Function],
toJSON: [Function],
toString: [Function],
isOk: [Function] }
callback: result.hasWriteErrors true
callback: result.getWriteErrors [
{
"code": 11000,
"index": 3,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }",
"op": {
"_id": 3
}
}
]
Collection~insertWriteOpResult
.第一个是
Collection~bulkWriteOpCallback
,第二个是更内部的。因此,在这种情况下,API 文档是错误的。正如我上面所说,这是由第 535 和 669 行的“错误”引起的。
hasWriteErrors()
和
getWriteErrors()
),由于没有记录此行为,我怀疑它可以在没有通知的情况下在以后的版本中更改,并且我的代码会中断。
最佳答案
问题实际上仅在于“Promise”如何解决以及错误信息如何传递,但当然真正的核心问题是存在 是 实际上,当任何“批量”操作设置为 { ordered: false }
时,都会返回“两者”错误和结果信息。 .如 NODE-1158 所述,此问题已在 3.x 版本的驱动程序中得到解决。其中还包含指向修复该问题的 future 分支中的提交的链接。
对此的“解决方法”是要注意,BulkWriteResult
中存在“两者”结果和错误信息。作为任何此类方法的“回调”调用结果返回的对象(注意 insertMany()
甚至 bulkWrite()
实际上包装了一个底层 Bulk API Implementation )。
用列表来演示:
const MongoClient = require('mongodb').MongoClient;
const uri = 'mongodb://localhost/test';
const testData = [1,2,3,3,4,5,6,6,7,8,9];
(async function() {
let db;
try {
db = await MongoClient.connect(uri);
await db.collection('test').remove();
// Expect an error here - but it's just the errors
try {
let result = await db.collection('test').insertMany(
testData.map( _id => ({ _id }) ),
{ "ordered": false }
);
console.log(result); // never gets here
} catch(e) {
console.dir(e);
console.log(JSON.stringify(e.writeErrors,undefined,2));
}
await db.collection('test').remove();
// Wrapped callback so we see what happens
try {
let result = await new Promise((resolve,reject) =>
db.collection('test').insertMany(
testData.map( _id => ({ _id }) ),
{ "ordered": false },
(err,result) => {
if (err) reject(result); // Because the errors are here as well
resolve(result);
}
)
);
console.log(result); // Never gets here
} catch(e) {
console.dir(e);
console.log(e.hasWriteErrors());
console.log(JSON.stringify(e.getWriteErrors(),undefined,2));
}
} catch(e) {
console.error(e);
} finally {
db.close();
}
})();
insertMany()
带有将要为某些值产生重复键错误的值列表。
Promise
应该由驱动程序的实现代码指示的返回只是将传递
err
回调结果在它包装的方法中是
reject()
陈述。这意味着我们去
catch
在这里阻塞并产生错误信息作为输出:
{ MongoError: [object Object]
at Function.MongoError.create (/home/neillunn/projects/bulkerror/node_modules/mongodb-core/lib/error.js:31:11)
at toError (/home/neillunn/projects/bulkerror/node_modules/mongodb/lib/utils.js:139:22)
at /home/neillunn/projects/bulkerror/node_modules/mongodb/lib/collection.js:701:23
at handleCallback (/home/neillunn/projects/bulkerror/node_modules/mongodb/lib/utils.js:120:56)
at /home/neillunn/projects/bulkerror/node_modules/mongodb/lib/bulk/unordered.js:465:9
at handleCallback (/home/neillunn/projects/bulkerror/node_modules/mongodb/lib/utils.js:120:56)
at resultHandler (/home/neillunn/projects/bulkerror/node_modules/mongodb/lib/bulk/unordered.js:413:5)
at /home/neillunn/projects/bulkerror/node_modules/mongodb-core/lib/connection/pool.js:469:18
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
name: 'MongoError',
message: 'write operation failed',
driver: true,
code: 11000,
writeErrors:
[ WriteError {
code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] },
WriteError {
code: [Getter],
index: [Getter],
errmsg: [Getter],
getOperation: [Function],
toJSON: [Function],
toString: [Function] } ] }
[
{
"code": 11000,
"index": 3,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }",
"op": {
"_id": 3
}
},
{
"code": 11000,
"index": 7,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 6 }",
"op": {
"_id": 6
}
}
]
MongoError
尽管我们设置了
{ ordered: false }
响应中没有“结果”信息。详细查看
WriteError
列表中的错误信息我们可以看到确实有关于产生的每个重复键错误的详细信息。
Promise
.但是底层方法不是这样,它仍然使用回调来实现。
result
来查看结果。反对
reject
当
err
存在。这告诉我们一个不同的故事:
BulkWriteResult {
ok: [Getter],
nInserted: [Getter],
nUpserted: [Getter],
nMatched: [Getter],
nModified: [Getter],
nRemoved: [Getter],
getInsertedIds: [Function],
getUpsertedIds: [Function],
getUpsertedIdAt: [Function],
getRawResponse: [Function],
hasWriteErrors: [Function],
getWriteErrorCount: [Function],
getWriteErrorAt: [Function],
getWriteErrors: [Function],
getLastOp: [Function],
getWriteConcernError: [Function],
toJSON: [Function],
toString: [Function],
isOk: [Function],
insertedCount: 9,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds:
{ '0': 1,
'1': 2,
'2': 3,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 6,
'8': 7,
'9': 8,
'10': 9 },
n: 9 }
true
[
{
"code": 11000,
"index": 3,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 3 }",
"op": {
"_id": 3
}
},
{
"code": 11000,
"index": 7,
"errmsg": "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 6 }",
"op": {
"_id": 6
}
}
]
err
我们现在看到
BulkWriteResult
在 catch 块中。我们知道我们到达那里是因为我们在该块中运行的特定代码来检查结果。
insertedIds
的列表。 .从检查中我们还可以看出
hasWriteErrors()
返回
true
,我们可以得到
WriteError
的列表我们已将其连载以便更好地观看。
BulkWriteResult
完全没有,而是让
err
返回
BulkWriteError
.
bulkWrite()
实现中的方法(不是“直接”
insertMany()
包装的内容)有一个稍微不同的问题,即实际上根本抛出“没有错误”,因为代码期待
result
成为
null
正如所描述的那样,它不是。
catch
对于使用
Promise
的默认实现中的异常.然而,应该应用完全相同的处理方法,通过手动包装回调并发送
result
通过
reject
优先于
err
当这两个都返回为 not
null
时.
关于javascript - 函数 insertMany() 无序 : proper way to get both the errors and the result?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46841162/
我一直在使用 Tensorflow 解决线性回归问题。我得到一条平坦的曲线 pred_y。我应该如何将我的曲线与观察的训练示例拟合? 这是我的 tensorflow 代码: # coding: utf
我浏览了这个网站,找不到类似的场景。我正在尝试运行以下代码 SELECT st.storeid, s.noofitems FROM salestrnsaction AS st, soldvia AS
请善待我,我是 Python 初学者:-) 现在,我发现编写 Python 程序的“最佳实践”是将主代码包装在“main”函数中,并执行 if "__main__"== __name__: 测试调用“
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 9 年前。 Improve
这个问题在这里已经有了答案: What is the reason to use the 'new' keyword at Derived.prototype = new Base (6 个答案)
我正尝试在 tomcat 上为我的 jersey webapp 创建一个用户登录页面,它的行为与网络上的所有其他页面一样。也就是说,用户会看到一个漂亮的登录页面而不是弹出窗口(如 BASIC tomc
我正在尝试让 Android 服务监听来电,当确实有来电时,获取来电号码并向其发送短信。 在我的服务中,我制作了一个PhoneStateListener: TelephonyManager tMana
是否有适当的地方来存储数据库的高级描述?类似于“此数据库用于存储 XYZ 以供 ABC 使用”之类的内容。这不一定是人们需要查询的信息,而是对管理系统的人有用的信息(即几个月前我试图记住几个月前我试图
下面的排序逻辑非常简单: 1. 标记不包含所选排序值的产品 2. 按所选排序值的数量降序对产品进行排序 3.隐藏不包含所选排序值的产品 我添加了简单的排序逻辑,它可以对元素进行排序(可以在控制台中预期
这个问题在这里已经有了答案: Where does Visual Studio look for C++ header files? (7 个答案) 关闭 9 年前。 所以,我在 VS2010 中开
我正在尝试连接到 MSMQ 并发送一些消息。不幸的是,项目中有关于如何做到这一点的“先前艺术”,我应该模仿它。之前的应用程序的连接方式如下: if (MSMQ in workgroup mode) {
我正在编写一个可能会被其他人使用的 ROS 节点,这就是我想要遵循通用指南的原因。有时我想为异常添加额外的信息,但我不知道该怎么做。这是一个方便的示例: 我的 ROS 节点使用 boost 库连接到串
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 4 年前。 Improve
我在摆弄 django-tinyMCE并注意到一些配置没有得到应用。这是我的 settings.py 中的代码 TINYMCE_DEFAULT_CONFIG = { 'theme' : 'ad
回顾我过去的项目,我经常遇到这个: 一位客户或经理向我提出一项任务并要求进行估算。我估计说 24 小时。他们还询问了业务分析师,据我所知,他们的经验大多是非技术性的。他们给出的估计是 16 小时。最后
我使用以下方式调用几个sql文件: :r C:\Scripts\Script1.sql :r C:\Scripts\Script2.sql :r C:\Scripts\Script3.sql 我对 :
在类构造函数中初始化 AS3 类变量“更好”吗?或者当我在类的顶部声明它们时,我可以将它们初始化为默认值吗?我问这个问题是因为当有很多类变量时,在一个地方声明它们然后在另一个地方初始化它们似乎效率很低
我有一个代码: $("#button").click(function () { for (var i = 0; i < 4; i++) {
我们的应用程序正在被翻译成多种语言,我们需要一个组合框来列出可能的语言。我们希望使用该语言的语言名称(例如,Français 表示法语)。 列出这些语言是否有任何“正确”的顺序?我们是否根据他们的
我正在尝试在 Ubuntu 12.04 中使用 Tramp/Emacs-23 来编辑远程主机文件。我的远程主机有两步验证 (RSA+Passwd)。我通过 .ssh/config 使用多路复用来确保
我是一名优秀的程序员,十分优秀!