我正在对mongodb数据库进行批量插入。我知道插入的99%的记录会因重复键错误而失败。我想在插入后打印有多少新记录插入到数据库中。所有这一切都是通过龙卷风马达mongodb驱动程序在python中完成的,但这可能并不重要。
try:
bulk_write_result = yield db.collections.probe.insert(dataarray, continue_on_error=True)
nr_inserts = bulk_write_result["nInserted"]
except pymongo.errors.DuplicateKeyError as e:
nr_inserts = ???? <--- what should I put here?
由于抛出异常,bulk_write_result
为空。显然我可以(除了并发问题)在插入之前和之后对完整集合进行计数,但是我不喜欢在日志文件中只有一行到数据库的额外往返。那么有什么方法可以发现实际插入了多少条记录?
答案 0 :(得分:3)
我不清楚为什么你yield
插入结果。但是,关于bulk inserts:
insert_many
,因为insert
已被弃用; ordered
关键字设置为False
时,如果出现错误,您的插入内容将继续; insert_many
会引发BulkWriteError
,您可以查询以获取插入的文档数。所有这些导致类似的事情:
try:
insert_many_result = db.collections.probe.insert_many(dataaray,ordered=False)
nr_inserts = len(insert_many_result.inserted_ids)
except pymongo.errors.BulkWriteError as bwe:
nr_inserts = bwe.details["nInserted"]
如果您需要识别写入错误背后的原因,则必须检查bwe.details['writeErrors']
数组。代码值11000表示&#34;重复键错误&#34;:
>>> pprint(e.details['writeErrors'])
[{'code': 11000,
'errmsg': 'E11000 duplicate key error index: test.w.$k_1 dup key: { : 1 }',
'index': 0,
'op': {'_id': ObjectId('555465cacf96c51208587eac'), 'k': 1}},
{'code': 11000,
'errmsg': 'E11000 duplicate key error index: test.w.$k_1 dup key: { : 3 }',
'index': 1,
'op': {'_id': ObjectId('555465cacf96c51208587ead'), 'k': 3}}
在这里,正如您所看到的,我尝试在w
db的test
集合中插入两个文档。由于重复的密钥错误,两个插入都失败了。
答案 1 :(得分:2)
使用continue_on_error进行常规插入无法报告您想要的信息。但是,如果您使用的是MongoDB 2.6或更高版本,我们的高性能解决方案具有良好的错误报告功能。这是使用Motor的BulkOperationBuilder的完整示例:
import pymongo.errors
from tornado import gen
from tornado.ioloop import IOLoop
from motor import MotorClient
db = MotorClient()
dataarray = [{'_id': 0},
{'_id': 0}, # Duplicate.
{'_id': 1}]
@gen.coroutine
def my_insert():
try:
bulk = db.collections.probe.initialize_unordered_bulk_op()
# Prepare the operation on the client.
for doc in dataarray:
bulk.insert(doc)
# Send to the server all at once.
bulk_write_result = yield bulk.execute()
nr_inserts = bulk_write_result["nInserted"]
except pymongo.errors.BulkWriteError as e:
print(e)
nr_inserts = e.details['nInserted']
print('nr_inserts: %d' % nr_inserts)
IOLoop.instance().run_sync(my_insert)
完整文档:http://motor.readthedocs.org/en/stable/examples/bulk.html
在2.6之前注意MongoDB上的批量插入性能不佳的警告!它仍然可以工作,但每个文档需要单独的往返。在2.6+中,驱动程序在一次往返中将整个操作发送到服务器,服务器报告成功的次数和失败次数。