Aggregation: merge does not commit to database

Trying to append the contents of one collection to another one. On the mongo command line, this is a simple

db.first_collection.aggregate( [ { $merge: { into: "second_collection" } } ] )

However, using the ruby driver, it seems that this command is not “committed” to the database, and the append actually never happens. The command I use in Ruby:

$db_handle[:first_collection].aggregate[ { "$merge" => { :into => "second_collection" } } ]

However, nothing seems to happen at the database level… How do I “commit” this to the database?

Thank you,
jan.

Hi @Jan_Aerts,

The issue you’re having is that by calling $db_handle[:first_collection].aggregate[ { "$merge" => { :into => "second_collection" } } ] the driver is only returning an instance of Mongo::Collection::View::Aggregation, not the results of the aggregation command.

Once you interact with this view instance the command will be executed and the $merge will produce results in the target collection.

The easiest way to do this is to call to_a on the view instance:

$db_handle[:first_collection].aggregate[ { "$merge" => { :into => "second_collection" } } ].to_a

Note that the same behavior would be seen with $out stages as well.

The following unit test can be used to demonstrate this:

require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'

  gem 'mongo'
  gem 'test-unit'
end

class TestAggregationOut < Test::Unit::TestCase
  def setup
    Mongo::Logger.logger.level = Logger::INFO
    @client = Mongo::Client.new([ '127.0.0.1:27017' ], database: 'test')
    @client[:foo].drop
    @client[:foo].insert_one( { driver: "ruby" } )
    @client[:bar].drop
  end

  def test_out_without_to_a
    result = @client[:foo].aggregate([ { :$out => "bar" } ])
    assert_equal @client[:foo].count, @client[:bar].count, "Count should match"
  end
  
  def test_out_with_to_a
    result = @client[:foo].aggregate([ { :$out => "bar" } ]).to_a
    assert_equal @client[:foo].count, @client[:bar].count, "Count should match"
  end

  def test_merge_without_to_a
    result = @client[:foo].aggregate([ { :$merge => { into: "bar" } } ])
    assert_equal @client[:foo].count, @client[:bar].count, "Count should match"
  end
  
  def test_merge_with_to_a
    result = @client[:foo].aggregate([ { :$merge => { into: "bar" } } ]).to_a
    assert_equal @client[:foo].count, @client[:bar].count, "Count should match"
  end

  def teardown
    @client = nil
  end
end