使用PyMongo 3.7.2,我试图通过在MongoDB游标上使用batch_size读取块中的集合,如here所述。基本思想是在collection对象上使用find()方法,并以batch_size作为参数。但是无论我如何尝试,游标始终会返回集合中的所有文档。
我的代码的基本片段如下所示(该集合包含1万多个文档):
import pymongo as pm
client = pm.MongoClient()
coll = client.get_database('db').get_collection('coll')
cur = coll.find({}, batch_size=500)
但是,光标总是立即返回完整的集合大小。我正在按照文档中的说明使用它。
有人知道我将如何适当地分批迭代集合吗?有多种方法可以遍历find()方法的输出,但是仍然可以首先获取完整的集合,并且仅可以遍历内存中已经提取的文档。应该使用batch_size参数进行批处理,并且每次都往返于服务器,以节省内存空间。
答案 0 :(得分:1)
Pymongo为Cursor
类提供了一些生活质量帮助器,因此它将自动为您进行批处理,并根据文档将结果返回给您。
已设置batch_size
设置,但是您的想法是,您只需要在find()
方法中进行设置,而不必进行手动的低级别调用或遍历批处理。
例如,如果我的收藏集中有100个文档:
> db.test.count()
100
然后我将profiling level设置为记录所有查询:
> db.setProfilingLevel(0,-1)
{
"was": 0,
"slowms": 100,
"sampleRate": 1,
"ok": 1,
...
然后我使用pymongo指定10的batch_size
:
import pymongo
import bson
conn = pymongo.MongoClient()
cur = conn.test.test.find({}, {'txt':0}, batch_size=10)
print(list(cur))
运行该查询,我在MongoDB日志中看到:
2019-02-22T15:03:54.522+1100 I COMMAND [conn702] command test.test command: find { find: "test", filter: {} ....
2019-02-22T15:03:54.523+1100 I COMMAND [conn702] command test.test command: getMore { getMore: 266777378048, collection: "test", batchSize: 10, ....
(getMore repeated 9 more times)
因此查询是从服务器中按指定批次提取的。它只是通过Cursor
类对您隐藏了。
修改
如果您真的需要批量获取文件,则在集合(doc link)下有一个函数find_raw_batches()
。此方法的工作方式类似于find()
,并且接受相同的参数。但是请注意,它将返回原始BSON,该原始BSON需要由应用程序在单独的步骤中进行解码。值得注意的是,此方法不支持sessions。
已经说过,如果目标是降低应用程序的内存使用量,则值得考虑修改查询,使其改为使用范围。例如:
find({'$gte': <some criteria>, '$lte': <some other criteria>})
范围查询更容易优化,可以使用索引,并且(在我看来)更容易调试,并且在查询中断时更容易重新启动。使用批处理时灵活性较差,在这种情况下,您必须从头开始重新启动查询,如果查询被打断,则必须再次遍历所有批处理。
答案 1 :(得分:1)
这就是我的方法,它有助于将数据分块,但我认为将有一种更直接的方法。我创建了yield_rows函数,该函数可让您生成并产生块,以确保删除使用的块。
vars
如果我找到一种更清洁,更有效的方法,我将更新我的答案。