30 亿文档的 Mongodb 不同聚合

标签 mongodb mapreduce mongodb-query aggregation-framework

我有一个包含 30 亿个文档的庞大集合。每个文档如下所示:

"_id" : ObjectId("54c1a013715faf2cc0047c77"),
"service_type" : "JE",
"receiver_id" : NumberLong("865438083645"),
"time" : ISODate("2012-12-05T23:07:36Z"),
"duration" : 24,
"service_description" : "NQ",
"receiver_cell_id" : null,
"location_id" : "658_55525",
"caller_id" : NumberLong("475035504705")

我想获取不同用户的列表(他们应该至少作为调用者“caller_id”出现一次)、他们的计数(每个用户作为调用者或接收者出现在集合中的次数)以及调用者的位置(即每个用户每个 location_id 的计数)。

我想以以下结尾:

"number_of_records" : 20,
"locations" : [{location_id: 658_55525, count:5}, {location_id: 840_5425, count:15}],
"user" : NumberLong("475035504705")

我尝试了描述的解决方案 herehere但它们效率不够(非常慢)。实现这一目标的有效方法是什么?

最佳答案

对结果使用聚合:

db.<collection>.aggregate([
   { $group : { _id : { user:  "$caller_id", localtion: '$location_id'} , count : { $sum : 1}  } },
   { $project : { _id : 0, _id : '$_id.user', location : '$_id.localtion', count : '$count' } },
   { $group : { _id : '$_id', 'locations' : { $push : { location_id : '$location', count : '$count' } }, number_of_records : {$sum : '$count'} } },
   { $project : { _id : 0, user : '$_id', locations : '$locations', number_of_records : '$number_of_records'} },
   { $out : 'outputCollection'},
])

输出将是:

{
    "0" : {
        "locations" : [ 
            {
                "location_id" : "840_5425",
                "count" : 8
            }, 
            {
                "location_id" : "658_55525",
                "count" : 5
            }
        ],
        "number_of_records" : 13,
        "user" : NumberLong(475035504705)
    }
}

更新使用allowDiskUse:

var pipe = [
   { $group : { _id : { user:  "$caller_id", localtion: '$location_id'} , count : { $sum : 1}  } },
   { $project : { _id : 0, _id : '$_id.user', location : '$_id.localtion', count : '$count' } },
   { $group : { _id : '$_id', 'locations' : { $push : { location_id : '$location', count : '$count' } }, number_of_records : {$sum : '$count'} } },
   { $project : { _id : 0, user : '$_id', locations : '$locations', number_of_records : '$number_of_records'} },
   { $out : 'outputCollection'},
];

db.runCommand(
   { aggregate: "collection",
     pipeline: pipe,
     allowDiskUse: true
   }
)

关于30 亿文档的 Mongodb 不同聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28117318/

相关文章:

javascript - 对子文档数组进行 elemMatch 搜索

mongodb - 如何在 mongodb 聚合中将毫秒转换为日期?

mongodb - 如何使用 Liferay 在 portlet 中下载文件或 InpuStream?

mongodb - Java MongoDB 一次保存多个文档

php - 在 amazon linux 上为 PHP 安装 mongo 驱动程序时出错

Javascript .find() 如何查找并返回所有用户名?

java - 如何使用 mapreduce 合并一些文件?

java - 在 MapReduce 中使用 MultipleTextOutputFormat 控制输出文件名

javascript - mongodb 按字符串长度分组

r - 如何在Rhadoop中的rmr map reduce中捕获R后台代码