Development configuration
One of the first things you'll encounter when starting your Rails app after upgrading to Mongoid 5 is an error about your database config being incorrect.
The fix is easy, just change sessions
to clients
:
development: clients: default: database: appsignal_development hosts: - localhost:27017
Driver changes
In our codebase we "drop down to the driver" a lot to execute queries directly on moped/mongo-ruby-driver, instead of using Mongoid, e.g. to create collections for each account. Here you'll also need to change session
to client
.
Another change is that read
now expects a hash with a :mode
key, instead of the value directly:
def create_log_entry_collection Mongoid .client('default') # used to be `.session('default')` .with(:read => {:mode => :primary}) # used to be `read: => :primary` .database .command(:create => 'foo') end
Moped has an insert
method that accepts either a single document or an array of documents. The new mongo-ruby-driver comes with two separate methods, and you should pick one depending on the amount of documents you'd like to insert:
# Before Mongoid.client('default')['foo'].insert(document) Mongoid.client('default')['foo'].insert([document, document]) # After Mongoid.client('default')['foo'].insert_one(document) Mongoid.client('default')['foo'].insert_many([document, document])
Lack of ordering
One of the biggest changes with the new driver is that documents are no longer ordered on _id
by default.
First and last no longer add an
_id
sort when no sorting options have been provided. In order to guarantee that a document is the first or last, it needs to now contain an explicit sort.
This means that anywhere where you rely on ordering (.first
, .last
) you need to explicitly order the query by _id
:
# Before expect( User.first.name ).to eq 'bob' expect( User.last.name ).to eq 'kelso' # After expect( User.asc('_id').first.name ).to eq 'bob' expect( User.asc('_id').last.name ).to eq 'kelso'
In order to make sure our code behaves as it used to, we created a concern that adds a default scope that orders by _id
:
# concerns/ordered_by_id_asc.rb module OrderedByIdAsc extend ActiveSupport::Concern included do default_scope -> { asc('_id') } end end
# models/account.rb class Account include Mongoid::Document include Mongoid::Timestamps include OrderedByIdAsc end
FindAndModify
Find_and_modify
has been removed. Instead you now have 3 methods to chose from:
find_one_and_update
find_one_and_replace
(Convenience method, callsfind_one_and_update
)find_one_and_delete
ExpireAfterSeconds
One of the more obscure changes is the way a TTL index is created. We use TTL indexes to automatically purge customer data depending on their plan (e.g. after 7 days, or after a month).
The option on the index used to be called expire_after_seconds
, but has been renamed to expire_after
:
# Before collection.indexes.create_one( {:time => 1}, {:expire_after_seconds => ttl} ) # After: collection.indexes.create_one( {:time => 1}, {:expire_after => ttl} )
Staging/Production config changes
While in development we only needed to change sessions
to clients
, but our staging/production configs needed a lot more work:
# Before staging: sessions: default: database: appsignal_main username: <%= ENV['MONGOID_USERNAME'] %> password: <%= ENV['MONGOID_PASSWORD'] %> hosts: - mongo1.staging:27017 - mongo2.staging:27017 - mongo3.staging:27017 options: read: :primary pool_size: {{ mongoid_pool_size }} ssl: ca_file: /etc/ssl/certs/root_ca.crt client_cert: /app/shared/config/mongodb_app.crt client_key: /app/shared/config/mongodb_app.key # After staging: clients: default: database: appsignal_main hosts: - mongo1.staging:27017 - mongo2.staging:27017 - mongo3.staging:27017 options: user: <%= ENV['MONGOID_USERNAME'] %> password: <%= ENV['MONGOID_PASSWORD'] %> read: mode: :primary max_pool_size: {{ mongoid_pool_size }} ssl: true ssl_ca_cert: /etc/ssl/certs/root_ca.crt ssl_cert: /app/shared/config/mongodb_app.crt ssl_key: /app/shared/config/mongodb_app.key replica_set: staging
username
has been renamed touser
and moved tooptions
password
has been moved tooptions
read
now expects a nested key namedmode
SSL
is no longer a nested hash, but is set underoptions
- The config requires a
replica_set
key if the setup is a replicaset
The upgrade documentation says that MongoDB 2.4 and 2.6 use :plain
auth, but we needed to remove the auth_mech
key all together for the setup to work.
Conclusion
Although this is quite an extensive list, we found the upgrade to be relatively painless and the new driver feels a lot more solid than the old Moped driver.
Wondering what you can do next?
Finished this article? Here are a few more things you can do:
- Try out AppSignal with a 30-day free trial.
- Reach out to our support team with any feedback or questions.
- Share this article on social media
Most popular AppSignal articles
Easily Monitor Multiple Heroku Apps with AppSignal
You can now monitor multiple Heroku apps from a single AppSignal instance.
See moreFine-Tune Your Charts with Minutely Metrics in AppSignal
Discover how minutely metrics in AppSignal deliver precise performance monitoring. Check out detailed performance data, spot anomalies quickly, troubleshoot issues more efficiently, and optimize your application's performance.
See moreSecure Your Sign-Ins with AppSignal's Single Sign-On
Secure team sign-ins and enhance access management with AppSignal's Single Sign-On Business Add-On. Integrate AppSignal with your identity provider for seamless, secure access management.
See more

Robert Beekman
As a co-founder, Robert wrote our very first commit. He's also our support role-model and knows all about the tiny details in code. Travels and photographs (at the same time).
All articles by Robert BeekmanBecome our next author!
AppSignal monitors your apps
AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!
