How to access MongoDB aggregation structure from rmongodb R package

I am trying to access the mongodb aggregation structure from rmongodb. It should be accessible through mongo.command (), but I cannot configure bson correctly.

Here is an example that can be reproduced. In R, set up a test collection:

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 } } } ] }) 

It seems that the following in R will achieve the same effect:

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

This does not work.

For this particular aggregation, I know that there are other ways to do this. I just provide it as a simple example, but in the future I want to move on to more complex aggregates.

Also, I know of another mongodb R package that I might consider to do the trick, but I have invested quite a lot in using this package right now.

+4
source share
2 answers

Firstly, the following code will give you the result you want:

 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); 

I found the task with executing aggregates in rmongodb is that the user:

  • it is almost necessary to use bson buffers
  • required to specify the argument of the pipeline as an array
  • should mark entries in the pipeline array with integers (I believe that this requires specifying the actual mechanics of aggregation as sub-bson objects)

I could be wrong about (3), although I did not see other examples where one could perform aggregation of “group”, which could cancel the statement.

Good luck

+2
source

Your code looks like it will create an aggregation pipeline with a scene named "group" and there is no such pipeline operator. The operator "$group" and it’s possible that this is the only thing that needs to be fixed.

However, I suspect that using list () with only one “element” creates a subdocument, rather than creating an array with one document, which should be a pipeline. You can try to explicitly create an array with one element, especially if this is the only way to get the "$ group" in the object correctly.

 ... mongo.bson.buffer.start.array(buf, "pipeline") mongo.bson.buffer.append(buf, "$group", ... etc mongo.bson.buffer.finish.object(buf) 
0
source

Source: https://habr.com/ru/post/1479065/


All Articles