我们有一个大约400万个条目的defaultdict,如:
my_dict = {'page_abc': 1234545, 'page_asdf': 54231}
我们有一个mongoDB集合,有大约1000万个条目,每个文档都是:
{'page':'page_abc', 'volume': 321, '_id':whatever}
这是由_id
(mongodb默认)和page
(我设置)索引。
我只需要使用存在的页面更新集合。我的代码最初是:
for page, volume in my_dict.iteritems():
entry = c.db.coll.find_one({'page':page})
if entry:
c.db.coll.update({'_id':entry['_id']},
{'$set':{'volume':entry['volume']+volume}})
但事实证明这需要大约3个小时。我只通过抓取一次收集来加速它:
for entry in c.db.coll.find():
if entry['page'] in my_dict:
c.db.coll.update({'_id':entry['_id']},
{'$set':{'volume'+log_file_date:my_dict[entry['page']]}})
大约需要58分钟。考虑到我每天都需要这样做,这仍然很慢。 这可以加快吗?
我现在的想法:
编辑:我计算了我的更新时间,我确实可以达到每秒3227次。可以改进吗?或者我达到了硬件限制(7200rpm seagate st2000dm001 cc43)
答案 0 :(得分:0)
我建议您使用$ inc运算符。这样您就不需要进行查找,您可以立即进行更新。这是代码:
for page, volume in my_dict.iteritems():
c.db.coll.update({'page':page},{'$inc':{'volume':volume}})
由于upsert参数未设置为True,因此当且仅当文档存在时才会更新文档。
编辑: 即使您想要添加新属性,也可以在一次调用中完成。我不明白为什么你需要做这个发现。这是代码:
for page, volume in my_dict.iteritems():
c.db.coll.update({'page':page},{'$set': {'volume'+log_file_date:my_dict['page']}})
答案 1 :(得分:0)
您的MongoDB系列中有多少个条目? 如果它减少了一个数量级,你可以将c.db.coll.distinct(' page')的结果放到内存中,然后在内存中过滤,而不是一个一个地查询到mongoDB。 如果集合包含太多条目,您可以将页面块化为块(让我们说 - 块中的1000页),然后在查找结果上运行不同({'页面&# 39;:{' $ in':block_of_pages}})。