Skip to content

Instantly share code, notes, and snippets.

Created Nov 27, 2017
What would you like to do?
changes observed from ruby mongo 1.x to 2.x

#Updating from mongo ruby drive 1.x to 2.x

We've recently been belatedly migrating to the 2.x series of the mongo ruby driver. At least in part this is because there's very little documentation out there on what has changed, except that there is no backwards compatibility. This post is a list of issues that we came across - I expect it is by no means exhaustive


Before you get started, make sure that any dependencies you have are also comaptible with mongo 2.x. For example database_cleaner needs to be 1.5 or higher

Class name changes

A lot of the classes / constants in the Mongo:: hierarchy have moved around. For us the lions share were exceptions we were rescuing, for example

Mongo::GridFileNotFound => Mongo::Error::FileNotFound
BSON::InvalidObjectId   => BSON::ObjectId::Invalid
Mongo::OperationFailure => Mongo::Error::OperationFailure

CRUD changes

Several of the methods here have been renamed or had their signature change slightly.


Previously Collection#find took a block and yielded a cursor, with the block used to determine the lifetime of the cursor. find now returns a view that can be iterated over. If you don't want the cursor to timeout, this option has been renamed from timeout: false to no_cursor_timeout: true


The old Mongo::Collection had an insert method that took either a single document or an array of documents and inserted them into the collection. You now need to use insert_one for the single document case and insert_many for the second case


Previously one of the options the update method took was a boolean multi: option that controlled whether mongodb should update all matching documents or only the first one. Instead call update_one or update_many


Deleting documents used to be via the remove method, with a limit option to control whether the first matching document was removed or all of them (the default). In 2.x, call delete_one or delete_many


In 1.x, Mongo::Collection#count took a single hash of options, which could include a query. In 2.x, the first argument is instead a query. For example

collection.count(query: {active: true}, {read: :secondary})


collection.count({active: true}, {read: {mode: :secondary}})


This used to look like

grid =
id = grid.put(data, opts) #data is string or has #read method
grid.get(id) #returns a gridio

In 2.x you would do

grid = database.fs

id = grid.upload_from_stream(filename, io)

grid.open_download_stream(id) do |stream|
  stream.each do |chunk| #you can also use stream.get
    # do something with data

Read preferences

Instead of {read: secondary}, use {read: {mode: :secondary}}

To execute a read against a secondary you can do

collection.with(read: {mode: :secondary}).find(...)


Previously you would do

collection.map_reduce(map_function, reduce_function, {query: {active: true}, ...})

This executes the map reduce operation and, for the inline result types, returns the data

If you wanted to perform that over a subset of the collection, then you added query: to the options.

In 2.x, map_reduce is a method on a view and doesn't accept a query option (or rather, it ignores it). The above code would look like

collection.find(active: true).map_reduce(map_function, reduce_function)

This in itself doesn't do anything than create a Mongo::View::MapReduce object. If you try to iterate over it, that will trigger execution of the map reduce operation. Node that

collection.find(active: true).map_reduce(map_function, reduce_function).map do |value|

returns the source of the map function, rather than executing Enumerable#map against the result set (use collect if you want this)

Aggregation pipeline

Like map reduce this now executes lazily. Some options have changed:

  • allowDiskUse is now allow_disk_use
  • cursor is now use_cursor

The read preference is now set on the collection/view rather than as an option to aggregate, ie

collection.with(:read => { :mode => :secondary }).aggregate(...)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment