我正在使用 Mongoid 和 Rails。我有一个名为“数据集”的集合,其中包含大约 600,000 个文档。每个数据集内部都有一个可能存在也可能不存在的关键"file"。文件内部有一个对象(文件)数组。我需要获取所有包含文件的数据集,然后获取这些数据集上所有文件的计数。这就是我所拥有的,但它抛出一个错误,指出它超出了最大文档大小:
total = Dataset.collection.aggregate([
{ '$project' => { files: 1 }},
{ '$unwind' => '$files' },
{ '$group' => {_id: "$_id", count: {'$sum' => 1} } }
])
我可以使用以下命令让它工作,但它太慢了,而且根本没有真正利用数据库的力量:
datasets_with_files = Dataset.where(:files.exists => true)
count = 0
datasets_with_files.each do |dataset|
count += dataset.files.count
end
count
所以基本上我需要知道 A. 最好的查询类型是什么,以及 B. 如果聚合是最好的方法,如何处理超过最大大小的文档,以便我可以执行这样的查询。
解决方案:
我不需要光标或磁盘使用就可以完成此工作:
Dataset.collection.aggregate([
{ '$match' => { files: { '$exists' => true }}},
{ '$unwind' => '$files' },
{ '$group' => { _id: nil, total_files: { '$sum' => 1 }}}
])[0]['total_files']
最佳答案
您可以使用 $size
直接投影数组字段的大小,因此在 shell 中您可以执行以下操作:
db.test.aggregate([
{$match: {files: {$exists: true}}},
{$project: {count: {$size: '$files'}}}
])
在 Ruby 中,它看起来像:
@coll.aggregate([
{ '$match' => { files: { '$exists' => true } } },
{ '$project' => { count: { '$size' => '$files' } } }
])
包含光标
选项以克服结果的 16MB 大小限制:
@coll.aggregate([
{ '$match' => { files: { '$exists' => true } } },
{ '$project' => { count: { '$size' => '$files' } } }
], cursor: {})
关于ruby-on-rails - MongoDB - 过滤和计算大型集合以进行统计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28732494/