使用rmongodb加速大型结果集处理

时间:2012-12-20 04:20:25

标签: r mongodb dataframe rmongodb bigdata

我正在使用rmongodb来获取特定集合中的每个文档。它可以工作,但我正在使用数百万个小文档,可能是100M或更多。我正在使用网站上作者建议的方法:cnub.org/rmongodb.ashx

count <- mongo.count(mongo, ns, query)
cursor <- mongo.find(mongo, query)
name <- vector("character", count)
age <- vector("numeric", count)
i <- 1
while (mongo.cursor.next(cursor)) {
    b <- mongo.cursor.value(cursor)
    name[i] <- mongo.bson.value(b, "name")
    age[i] <- mongo.bson.value(b, "age")
    i <- i + 1
}
df <- as.data.frame(list(name=name, age=age))

这适用于数百或数千个结果但是循环非常非常慢。有什么方法可以加快速度吗?也许是多处理的机会?任何建议,将不胜感激。我平均每小时1M,按照这个速度,我只需要一周的时间来建立数据框架。

编辑: 我注意到while循环中的矢量越多,它就越慢。我现在正试图为每个向量分别循环。虽然看起来仍然像黑客,但必须有更好的方法。

编辑2: 我对data.table运气不错。它仍在运行,但看起来它将在4小时内完成12M(这是我目前的测试设置),这是进步但远非理想

dt <- data.table(uri=rep("NA",count),
                 time=rep(0,count),
                 action=rep("NA",count),
                 bytes=rep(0,count),
                 dur=rep(0,count))

while (mongo.cursor.next(cursor)) {
  b <- mongo.cursor.value(cursor)
  set(dt, i, 1L,  mongo.bson.value(b, "cache"))
  set(dt, i, 2L,  mongo.bson.value(b, "path"))
  set(dt, i, 3L,  mongo.bson.value(b, "time"))
  set(dt, i, 4L,  mongo.bson.value(b, "bytes"))
  set(dt, i, 5L,  mongo.bson.value(b, "elaps"))

}

2 个答案:

答案 0 :(得分:3)

您可能想尝试mongo.find.exhaust选项

cursor <- mongo.find(mongo, query, options=[mongo.find.exhaust])

如果实际适用于您的用例,这将是最简单的修复。

然而,rmongodb驱动程序似乎缺少其他驱动程序可用的一些额外功能。例如,JavaScript驱动程序具有Cursor.toArray方法。这会直接将所有查找结果转储到数组中。 R驱动程序具有mongo.bson.to.list函数,但mongo.cursor.to.list可能是您想要的。可能值得向驱动程序开发人员寻求建议。

一个hacky解决方案可能是创建一个新的集合,其文档是每个原始文档100000的数据“块”。然后可以使用mongo.bson.to.list有效地读取这些中的每一个。可以使用mongo服务器MapReduce功能构建分块集合。

答案 1 :(得分:1)

我知道没有更快的方式来做到这一点。您正在从外部应用程序导入数据并使用解释语言,并且rmongodb无法预测集合中文档的结构。当你处理成千上万的文件时,这个过程本来就很慢。