6

我正在使用 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))

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

编辑:我注意到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"))

}

4

2 回答 2

3

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

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

如果确实适用于您的用例,这将是最简单的解决方法。

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

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

于 2012-12-20T19:08:12.420 回答
1

我不知道以一般方式执行此操作的更快方法。您正在从外部应用程序导入数据并使用解释语言,rmongodb 无法预测集合中文档的结构。当您处理数以千计的文档时,这个过程本身就很慢。

于 2012-12-20T21:46:52.797 回答