以资源友好的方式将巨大的Mongo结果集写入磁盘w / Python

时间:2011-09-25 19:16:36

标签: python mongodb

有一个包含> 500万件物品的Mongo系列。我需要获得所有“文档”的单个属性的“表示”(保存在变量中,或放入磁盘上的文件,此时的任何内容)。

我的查询是这样的:

cursor = db.collection.find({"conditional_field": {"subfield": True}}, {"field_i_want": True})

我的第一个,愚蠢的尝试是Pickle'光标',但我很快意识到它不能那样工作。

在这种情况下,“field_i_want”包含一个Integer。作为我尝试过的一个例子,我做了这个,几乎锁定了服务器几分钟:

ints = [i['field_i_want'] for i in cursor]

...只获取整数列表。这导致服务器上的CPU资源耗费太长时间。

是否有一种远程简单的方法可以将这些结果检索到列表,元组,集合,pickle,文件等中,这些内容不会完全占用cpu?

理想情况下,我可以转储结果以便稍后回读。但我希望在倾倒它们时尽可能善良。

2 个答案:

答案 0 :(得分:1)

我认为流式传输结果可能对此有所帮助:

with open("/path/to/storage/file", "w") as f:
    for row in cursor:
        f.write(row['your_field'])

如果不需要,请不要将所有内容都保留在内存中。

答案 1 :(得分:0)

虽然已经接受了,但我补充说你也可以考虑添加一个索引。我们很容易认为我们已经耗尽了mongo的'带宽',但它有'mongo'是有原因的!根据数据库的结构,500万响应可以非常快;听起来总的来说你的数据大概是500万整数?为简单起见,我们假设field_i_want等是包含字段名称的变量。如果你这样做:

db.collection.ensure_index([(conditional_field, DESCENDING), (field_i_want, ASCENDING)])
例如,您将能够执行“覆盖查询”,如下所示:

db.collection.find({conditional_field:True},fields={field_i_want:1, _id:-1})

有时pymongo会随意决定将mongodb的字典语法翻译成一个列表,就像上面的ensure_index和fields的情况一样。我相信你可以使用字典作为字段,这对于覆盖查询是必要的,但如果不是,你需要使用列表来研究如何使用笨拙的语法进行覆盖查询。覆盖查询的重要一点是只返回属于索引的字段。因此,您不需要“_id”,因为虽然“_id”会自动编入索引,但它不是将要使用的索引的一部分。使用覆盖查询执行查询时没有时间。它会立即为您提供所需的所有数据。如果您希望将其作为列表而不是字典列表(“文档”),您可以采取响应并执行以下操作:

[y for x,y in myquery.items()]

Mongo已经是一个二进制表示,它擅长存储,所以这可能是其中一个问题,其中最好的答案是不断磨练问题。如果您只想要转储,可以使用mongo附带的实用程序,并且可以在与mongod二进制文件相同的目录中找到它。这将允许您将数据存入json,存储为文件(但同样,它当前存储为bson中的文件)。