1

I am trying to implement this solution in rails, using the collection aggregate method, to clone an entire collection within the same database.

In mongo shell, this works perfectly, and a cloned collection is created successfully:

db.source_collection.aggregate([ { $match: {} }, { $out: "target_collection" } ])

The rails-mongoid alternate, according to my research, should be this, which runs without errors:

SourceCollection.collection.aggregate({"$match" => {},  "$out" => "target_collection"})
#<Mongo::Collection::View::Aggregation:0x000000055bced0 @view=#<Mongo::Collection::View:0x44951600 namespace='DB_dev.source_collection' @filter={} @options={}>, @pipeline={"$match"=>{}, "$out"=>"target_collection"}, @options={}>

I also tried with an array

SourceCollection.collection.aggregate([{"$match" => {}},  {"$out" => "target_collection"}])
#<Mongo::Collection::View::Aggregation:0x000000054936d0 @view=#<Mongo::Collection::View:0x44342320 namespace='DB_dev.source_collection' @filter={} @options={}>, @pipeline=[{"$match"=>{}}, {"$out"=>"target_collection"}], @options={}>

UPDATE

This simplest syntax also works in Mongo console:

db.source_collection.aggregate( { $out: "target_collection" } )

But the respective syntax does not seem to work in Ruby:

SourceCollection.collection.aggregate({"$out" => "target_collection"})

Unfortunately, although there are no errors, the collection is not created.

Any clues as to the way I can make this happen? Mongo gem version 2.5.3

Update2

Apparently $out is not considered in the pipeline, thus rendering the aggregation invalid.

This can be fixed with code... I am looking for a module/class/method override, as contacting mongodb issue tracking system for a change request might not be as quick..

UPDATE - FINAL

This issue has been solved, by help of Thomas R. Koll (thank you).

I add an update to post the response I got from the ticketing service of MongoDB, which pretty much describes Thomas's solution.

The reason you're not seeing the results without count is that the aggregate method returns a lazy cursor; that is, the query does not execute until the return value of aggregate is iterated over. Calling count is one way to do this. This is the same behavior you'll see if you call find or if you call aggregate without specifying $out; the difference is that $out has an side-effect beyond just returning the results, so it's more obvious when exactly it occurs.

Ruby Racer
  • 5,690
  • 1
  • 26
  • 43
  • Whatever the answer, it won't have anything to do with mongoid as that is just a data mapper on top of the ruby mongo gem/driver. mongoid doesn't provide the `aggregate` method, only the mongo gem does that. – Thomas R. Koll Jun 02 '18 at 12:44
  • @ThomasR.Koll You are right, of course. I have realized that, I just forgot to remove the tag. – Ruby Racer Jun 02 '18 at 14:54

1 Answers1

2

Found the solution, and I have to explain a few thigs:

This returns a Mongo::Collection::View::Aggregation object, it won't send a query to the database

User.collection.aggregate({"$out": "target_collection"})

Only when you call a method like count or to_a on the aggregation object it will be sent to the server, but if you pass a hash you'll get an error, so the pipeline has to be an array of hashes to work

User.collection.aggregate([{"$out": "target_collection"}]).count
Thomas R. Koll
  • 3,131
  • 1
  • 19
  • 26
  • Mister, you are a saint :). This is a very intuitive workaround that actually works. Thank you so much! – Ruby Racer Jun 02 '18 at 14:56
  • With 9 years of mongodb exp I gotta know a bit, right :) Greetings to Greece, I miss it. – Thomas R. Koll Jun 02 '18 at 15:06
  • 1
    Greetings from Greece to you too. I am only a couple of mongo-months old, but I get the feeling that I will grow mongold as well :). Cheers, keep up the good work. – Ruby Racer Jun 02 '18 at 15:11
  • Doesn't work for me. Also, I need to know how to do the equivalent of db.target_collection.aggregate in MongoID – Wylliam Judd Oct 29 '18 at 20:16
  • @WylliamJudd Mongoid doesn't have aggregate, only the underlying `Mongo` module has. You probably want to read the documentation first, try out the examples in there and open a new question if you still have unanswered points https://docs.mongodb.com/manual/reference/operator/aggregation/out/ – Thomas R. Koll Oct 30 '18 at 23:24
  • Oh I see. Still the mongodb docs won't help me, I'll need documentation on the Mongo Ruby on Rails module. – Wylliam Judd Oct 30 '18 at 23:52
  • please open a new question @WylliamJudd – Thomas R. Koll Nov 01 '18 at 06:42