MongoDB - 筛选和统计大型集合以进行统计
MongoDB - Filter and count large collections for statistics
我在 Rails 中使用 Mongoid。我有一个名为 "datasets" 的集合,其中包含大约 600,000 个文档。在每个数据集中,都有一个可能存在也可能不存在的键 "files"。在文件内部有一个对象(文件)数组。我需要获取所有包含文件的数据集,然后计算这些数据集上的所有文件。这就是我所拥有的,但它抛出一个错误,说它超过了最大文档大小:
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' } } }
])
包括 cursor
选项以克服结果的 16MB 大小限制:
@coll.aggregate([
{ '$match' => { files: { '$exists' => true } } },
{ '$project' => { count: { '$size' => '$files' } } }
], cursor: {})
我在 Rails 中使用 Mongoid。我有一个名为 "datasets" 的集合,其中包含大约 600,000 个文档。在每个数据集中,都有一个可能存在也可能不存在的键 "files"。在文件内部有一个对象(文件)数组。我需要获取所有包含文件的数据集,然后计算这些数据集上的所有文件。这就是我所拥有的,但它抛出一个错误,说它超过了最大文档大小:
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' } } }
])
包括 cursor
选项以克服结果的 16MB 大小限制:
@coll.aggregate([
{ '$match' => { files: { '$exists' => true } } },
{ '$project' => { count: { '$size' => '$files' } } }
], cursor: {})