我有以下可用的代码。它遍历并找到比指定日期更新并且与正则表达式匹配的每个文件,然后删除它,以及指向它的块。
conn = new Mongo("<url>");
db = conn.getDB("<project>");
res = db.fs.files.find({"uploadDate" : { $gte : new ISODate("2017-04-04")}}, {filename : /.*(png)/});
while (res.hasNext()) {
var tmp = res.next();
db.getCollection('fs.chunks').remove({"files_id" : tmp._id});
db.fs.files.remove({ "_id" : tmp._id});
}
这是非常缓慢的,而且大部分时间,客户端我都是在短时间内运行它。
另外,我知道我正在从文件系统中删除文件,而不是从正常的集合中删除。这是一个很长的故事,但上面的代码完全符合我的要求。
如何让它更快地运行? 我之前曾向我指出,我在客户端上运行此代码,但是可以在服务器端运行它吗?在我尝试使用Javascript驱动程序之前,这可能就是为什么。我假设使用Mongo shell在服务器上执行everythin。
任何帮助将不胜感激。如此接近,但到目前为止......
答案 0 :(得分:2)
我知道我正在从文件系统中删除文件,而不是从正常的集合中删除文件
GridFS是用于在MongoDB中存储二进制数据的规范,因此您实际上是从MongoDB集合中删除文档而不是从文件系统中删除文件。
我之前曾向我指出,我在客户端上运行此代码,但是可以在服务器端运行它吗?
您的MongoDB服务器正在执行您的大部分代码(查询和命令)。客户端(在这种情况下为mongo
shell)没有进行任何重要的处理。
这是非常缓慢的,而且大部分时间,客户端我都是在短时间内运行它。
您需要调查花费的时间。
如果您的mongo
shell与部署之间存在网络延迟问题,则可以考虑从靠近部署的mongo
shell会话运行查询(如果可能)或使用与较小范围的文件。
另一个值得研究的明显候选者是服务器资源。例如,删除大量文件会对I / O或RAM造成压力吗?在这种情况下,减少在每个脚本运行中删除的文档数量也可能有所帮助。
db.fs.files.find({“uploadDate”:{$ gte:new ISODate(“2017-04-04”)}},{filename:/.*(png)/})
此查询可能没有按预期执行:filename
作为find()
的第二个选项提供(因此用于投影而不是搜索条件)并且正则表达式匹配文件名在任何地方都包含png
(例如:typng.doc
)。
我假设使用Mongo shell在服务器上执行everythin。
这是一个不正确的一般假设。 mongo
shell可以评估本地函数,因此根据您的代码,可能存在在客户端上下文而不是服务器上下文中执行/评估的方面。您的示例代码正在运行在服务器上处理的查询/命令,但正在fs.files
shell中访问find()
查询返回的mongo
文档,以便构造要删除的查询fs.chunks
中的相关文件。
如何让它更快地运行?
除了上面提到的评论之外,您还可以进行一些代码更改以提高效率。特别是,您当前正在单独删除块文档。 MongoDB 2.6+中有Bulk API,这将减少每批删除所需的往返次数。
尝试提高速度的其他一些建议:
在{uploadDate:1, filename: 1}
上添加索引以支持您的find()
查询:
db.fs.files.createIndex({uploadDate:1, filename: 1})
使用批量API删除匹配的块文档而不是单个删除:
while (res.hasNext()) {
var tmp = res.next();
var bulk = db.fs.chunks.initializeUnorderedBulkOp();
bulk.find( {"files_id" : tmp._id} ).remove();
bulk.execute();
db.fs.files.remove({ "_id" : tmp._id});
}
向fs.files
查询添加投影,仅包含您需要的字段:
var res = db.fs.files.find(
// query criteria
{
uploadDate: { $gte: new ISODate("2017-04-04") },
// Filenames that end in png
filename: /\.png$/
},
// Only include the _id field
{ _id: 1 }
)
注意:除非您在GridFS文件中添加了大量元数据(或者要删除大量文件),否则这可能不会产生重大影响。默认的fs.files
文档大约是130个字节,但是您需要的唯一字段是_id
(12字节的ObjectId)。