Mur*_*ese 3 python mongodb gridfs mongodb-query
我有一个引用 GridFS 文件的集合,通常每条记录 1-2 个文件。这些集合相当大 - 父集合中大约有 705k 条记录,以及 790k GridFS 文件。随着时间的推移,出现了许多孤立的 GridFS 文件 - 父记录已被删除,但引用的文件并未被删除。我现在正尝试从 GridFS 集合中清除孤立文件。
这里建议的方法的问题在于,将 700k 记录组合成一个大的 ids 列表会导致内存中大约 4mb 的 Python 列表 - 将其传递到 Mongo 中 fs.files 集合上的 $nin 查询实际上需要永远。执行相反的操作(获取 fs.files 中所有 id 的列表并查询父集合以查看它们是否存在)也需要很长时间。
有人遇到过这个问题并开发出更快的解决方案吗?
首先,让我们花点时间考虑一下GridFS 到底是什么。首先,让我们阅读所引用的手册页:
GridFS 是用于存储和检索超过 BSON 文档大小限制16MB 的文件的规范。
因此,排除了这一点,这很可能就是您的用例。但这里要吸取的教训是,GridFS不会自动成为存储文件的“首选”方法。
在您的情况(和其他情况)中发生的情况是由于“驱动程序级别”规范(MongoDB 本身在这里没有魔法),您的“文件”已被“拆分”到两个集合中。一个集合用于内容的主要参考,另一个集合用于数据的“块”。
您的问题(和其他问题)是,既然“主要”引用已被删除,您已经设法留下了“块”。那么数量众多,如何摆脱孤儿呢。
您当前的阅读内容是“循环和比较”,并且由于 MongoDB不执行 join,所以确实没有其他答案。但有些事情可以提供帮助。
因此,与其运行一个巨大的$nin,不如尝试做一些不同的事情来打破这个局面。考虑按相反的顺序进行操作,例如:
db.fs.chunks.aggregate([
{ "$group": { "_id": "$files_id" } },
{ "$limit": 5000 }
])
Run Code Online (Sandbox Code Playgroud)
因此,您要做的就是从所有条目中获取不同的“files_id”值(即对 的引用fs.files),从 5000 个条目开始。然后你当然会回到循环,检查fs.files匹配的_id. 如果未找到某些内容,请从“块”中删除与“files_id”匹配的文档。
但这只是 5000,所以保留在该集合中找到的最后一个id ,因为现在您将再次运行相同的聚合语句,但有所不同:
db.fs.chunks.aggregate([
{ "$match": { "files_id": { "$gte": last_id } } },
{ "$group": { "_id": "$files_id" } },
{ "$limit": 5000 }
])
Run Code Online (Sandbox Code Playgroud)
所以这是有效的,因为这些ObjectId值是单调的或“不断增加”的。因此所有新条目总是大于上一个条目。然后您可以再次循环这些值,并在找不到的地方执行相同的删除操作。
这会“永远”吗?嗯,是。您可以db.eval()为此雇用,但请阅读文档。但总的来说,这是您使用两个集合所付出的代价。
回到起点。GridFS规范是这样设计的,因为它特别希望解决 16MB 的限制。但如果这不是您的限制,那么首先要问为什么要使用GridFS 。
MongoDB在给定 BSON 文档的任何元素中存储“二进制”数据都没有问题。所以你不需要仅仅使用GridFS来存储文件。如果您这样做了,那么您的所有更新都将完全是“原子的”,因为它们一次仅作用于一个集合中的一个文档。
由于GridFS 故意将文档拆分到集合中,因此如果您使用它,那么您将承受痛苦。因此,如果您需要它,请使用它,但如果您不需要,则只需将其存储BinData为普通字段,这些问题就会消失。
但至少你有一个比将所有内容加载到内存中更好的方法。
| 归档时间: |
|
| 查看次数: |
3291 次 |
| 最近记录: |