4

我正在尝试从 rmongodb 访问 mongodb 聚合框架。它应该可以通过 mongo.command() 获得,但我无法让 bson 正确。

这是一个可复制的例子。在 R 中,设置一个测试集合:

mongo <- mongo.create()
db <- "test"
ns <- "test.people"

buf <- mongo.bson.buffer.create()
mongo.bson.buffer.append(buf, "name", "John")
mongo.bson.buffer.append(buf, "age", 22L)
b <- mongo.bson.from.buffer(buf)
mongo.insert(mongo, ns, b);

buf <- mongo.bson.buffer.create()
mongo.bson.buffer.append(buf, "name", "John")
mongo.bson.buffer.append(buf, "age", 35L)
b <- mongo.bson.from.buffer(buf)
mongo.insert(mongo, ns, b);

buf <- mongo.bson.buffer.create()
mongo.bson.buffer.append(buf, "name", "Fred")
mongo.bson.buffer.append(buf, "age", 27L)
b <- mongo.bson.from.buffer(buf)
mongo.insert(mongo, ns, b);

Now, on the mongo console, the following works:

use test
db.runCommand({
  aggregate : "people", pipeline : [
  { $group :
    { _id    : '$name',
      total  : { $sum : 1 } } } ]
})

似乎 R 中的以下内容会达到相同的效果:

mongo.command(mongo, "test", list(
   aggregate="people", 
   pipeline=list(
      group=list(
         "_id"="$name",
         total=list("$sum"=1)
      )
   )
))

这不起作用。

对于这个特定的聚合,我知道还有其他方法可以做到这一点。我只是将它作为一个简单的示例提供,但我想在将来进行更复杂的聚合。

另外,我知道另一个用于 mongodb 的 R 包,我可能可以研究它来解决这个问题,但我现在投入了大量资金来使用这个包。

4

2 回答 2

2

首先,以下代码将为您提供所需的结果:

sub.buf <- mongo.bson.buffer.create();
  mongo.bson.buffer.start.object(sub.buf, "$group");
  mongo.bson.buffer.append(sub.buf, "_id", "$name"); 
    mongo.bson.buffer.start.object(sub.buf, "total");
    mongo.bson.buffer.append(sub.buf, "$sum", 1L); 
    mongo.bson.buffer.finish.object(sub.buf);
  mongo.bson.buffer.finish.object(sub.buf);
sb <- mongo.bson.from.buffer(sub.buf);

buf <- mongo.bson.buffer.create();
mongo.bson.buffer.append(buf, "aggregate", "people"); 
  mongo.bson.buffer.start.array(buf, "pipeline");
    mongo.bson.buffer.append(buf, "0", sb);
  mongo.bson.buffer.finish.object(buf);
cmd <- mongo.bson.from.buffer(buf);

我发现在 rmongodb 中执行聚合的挑战在于用户:

  1. 几乎需要使用 bson 缓冲区
  2. 需要将管道参数指定为数组
  3. 必须用整数标记管道数组中的条目(我相信这需要将实际的聚合机制指定为子 bson 对象)

我对 (3) 的看法可能是错误的,尽管我在任何地方都没有看到任何其他关于如何执行“组”聚合的示例,这会打折该语句。

祝你好运!

于 2013-06-20T18:50:19.963 回答
0

您的代码看起来会生成带有阶段命名的聚合管道,"group"并且没有这样的管道运算符。操作员是"$group"并且有可能这是唯一需要纠正的事情。

但是,我怀疑使用只有一个“元素”的 list() 会创建一个子文档,而不是创建一个包含一个文档的数组,这应该是管道。您可以尝试使用单个元素显式创建一个数组,特别是如果这是在对象中正确获取“$group”的唯一方法。

... 
mongo.bson.buffer.start.array(buf, "pipeline") 
mongo.bson.buffer.append(buf, "$group", ... etc 
mongo.bson.buffer.finish.object(buf)
于 2013-05-19T01:39:12.700 回答