Getting Started

Prerequisites

There are a few things you need to have in your toolbox before tackling a web application using Mongoid.

  • A good to advanced knowledge of Ruby.
  • Have good knowledge of your web framework if using one.
  • A thorough understanding of MongoDB.

This may seem like a "thank you Captain Obvious" moment, however if you believe that you can just hop over to Mongoid because you read a blog post on how cool Ruby and MongoDB were, you are in for a world of pain.

Mongoid leverages many aspects of the Ruby programming language that are not for beginner use, and sending the core team into a frenzy tracking down a bug for a common Ruby mistake is a waste of our time, and all of the other users of the framework as well.

THE DATABASE IS NOT A BLACK BOX.

Mongoid is an abstraction to make application developers' lives easier, however the internals leverage the power of MongoDB and it is truly important to know what is going on under the covers. This is why the documentation provides the exact queries that Mongoid is executing against the database when you call a persistence operation. If we took the time to tell you, you should listen. :)

Installation

The preferred method for installing Mongoid is with bundler. Simply add Mongoid to your Gemfile.

gem "mongoid", "~> 4.0.0"

Alternatively you can get the Mongoid gem direcly from rubygems.org:

$ gem install mongoid
The minimum version of MongoDB that is required for you to run Mongoid 4.0.0 is 2.4.0.

Configuration

Mongoid configuration can be done through a mongoid.yml that specifies your options and database sessions. The simplest configuration is as follows, which sets the default session to "localhost:27017" and provides a single database in that session named "mongoid".

development:
  sessions:
    default:
      database: mongoid
      hosts:
        - localhost:27017

Rails Applications

You can generate a config file by executing the generator and then editing myapp/config/mongoid.yml to your heart's desire. Mongoid will then handle everything else from there.

$ rails g mongoid:config

When Mongoid loads its configuration, it chooses the environment to used based on the following order:

  • Rails.env if using Rails.
  • Sinatra::Base.environment if using Sinatra.
  • RACK_ENV environment variable.
  • MONGOID_ENV environment variable.

If you are not using any rack based application and want to override the environment programatically, you can pass a second paramter to load! and Mongoid will use that.

Mongoid.load!("path/to/your/mongoid.yml", :production)

Anatomy of a Mongoid Config

Let's have a look at a full-blown mongoid.yml and explain the full power of what Mongoid can do. The following configuration has its explanation in the comments above each key.

# Tell Mongoid which environment this configuration is for.
production:
  # This starts the session configuration settings. You may have as
  # many sessions as you like, but you must have at least 1 named
  # 'default'.
  sessions:
    # Define the default session.
    default:
      # A session can have any number of hosts. Usually 1 for a single
      # server setup, and at least 3 for a replica set. Hosts must be
      # an array of host:port pairs. This session is single server.
      hosts:
        - flame.mongohq.com:27017
      # Define the default database name.
      database: mongoid
      # Since this database points at a session connected to MongoHQ, we must
      # provide the authentication details.
      username: user
      password: password
    # This defines a secondary session at a replica set.
    replica_set:
      # This configuration is a 3 node replica set.
      hosts:
        - dedicated1.myapp.com:27017
        - dedicated2.myapp.com:27017
        - dedicated3.myapp.com:27017
      database: mongoid
      # We can set session specific options, like reads executing
      # on secondary nodes, and defaulting the session to safe mode.
      options:
        read: :secondary
        write:
          w: :majority
    # This defines a tertiary session at a Mongos fronted shard.
    shard:
      # This configuration is a Mongos shard server.
      hosts:
        - mongos.myapp.com:27017
      database: mongoid
    # This configuration shows an authenticated replica set via a uri.
    another:
      uri: mongodb://user:pass@59.1.22.1:27017,59.1.22.2:27017/mongoid
  # Here we put the Mongoid specific configuration options. These are explained
  # in more detail next.
  options:
    include_root_in_json: true
    include_type_for_serialization: true
    # Note this can also be true if you want to preload everything, but this is
    # almost never necessary. Most of the time set this to false.
    preload_models:
      - Canvas
      - Browser
      - Firefox
    scope_overwrite_exception: true
    raise_not_found_error: false
    use_activesupport_time_zone: false
    use_utc: true

Configuration options

Mongoid currently supports the following configuration options, either provided in the mongoid.yml or programatically (defaults in parenthesis).

  • include_root_in_json(false): When set to true mongoid will include the name of the root document and the name of each association as the root element when calling #to_json on a model.
  • include_type_for_serialization(false): When set to true this will tell Mongoid to include the "_type" field when serializing to JSON and XML.
  • preload_models(false): Tells Mongoid to preload application model classes on each request in environments where classes are not being cached. Specify an array of class names when enabling, only to the classes that use inheritance.
  • protect_sensitive_fields(true): Mongoid by default will auto protect '_id' and '_type' from mass assignment. Set this to false if you are daring with your application's security.
  • raise_not_found_error(true): Will raise a Mongoid::Errors::DocumentNotFound when attempting to find a document by an id that doesnt exist. When set to false will only return nil for the same query.
  • scope_overwrite_exception(false): This will instruct Mongoid to raise an error if you define a scope with the same name as an existing method.
  • use_activesupport_time_zone(true): When in a Rails app will tell Mongoid to convert all times in the application to the local defined time zone in Active Support.
  • use_utc(false): Instructs Mongoid to convert all times to UTC times in all cases.

If you would like to see samples, there is one in the Mongoid repository and one in the Echo sample application.

Getting Rid of Active Record

Now that you have a mongoid.yml you can't wait to delete that pesky database.yml, right? Do it and you'll start getting ActiveRecord errors all over the place. You don't need ActiveRecord unless you're trying to use Mongo in concert with a SQL database. Here's how you remove ActiveRecord from the most recent version of Rails.

Open myapp/config/application.rb and near the top, remove the line require "rails/all" and add the following lines so you end up with this:

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie" # Comment this line for Rails 4.0+
require "rails/test_unit/railtie"
# require "sprockets/railtie" # Uncomment this line for Rails 3.1+

For Rails 3.2+ you'll also need to remove configuration options for Active Record that reside in your environments, ie myapp/config/environments/development.rb. Make sure any references to active_record are commented out like as follows

# Rails 3.2+, < 4.0
# config.active_record.mass_assignment_sanitizer = :strict
# config.active_record.auto_explain_threshold_in_seconds = 0.5
#
# Rails 4.0+
# config.active_record.migration_error = :page_load

For Rails 3.2.3+ but < 4.0 you'll also need to comment out the following line in myapp/config/application.rb.

# config.active_record.whitelist_attributes = true

You can also generate your new rails app sans Active Record like so.

rails new app_name --skip-active-record

Sinatra, Padrino, and others

You can create your mongoid.yml and place it anywhere you like. Just be sure that on application initialization you do the following:

Mongoid.load!("path/to/your/mongoid.yml")

Logging

Changing logging options is done simply by telling Mongoid or Moped's logger to have a different level. Logging is turned off by default.

module MyApplication
  class Application < Rails::Application
    Mongoid.logger.level = Logger::DEBUG
    Moped.logger.level = Logger::DEBUG
  end
end

If you want to change the logger instance, you can simply just set a new one.

Mongoid.logger = Logger.new($stdout)
Moped.logger = Logger.new($stdout)

Replica Sets

For replica sets, you only need to put each member of the replica set under the hosts section in your mongoid.yml - Mongoid and Moped will take care of the rest. The default read option is :primary, which means that reads will happen on the primary node. If you don't want this, switch this option to :secondary, which will send reads to the secondary(slaves) nodes.

sessions:
  default:
    hosts:
      - repl0.myapp.com:27017
      - repl1.myapp.com:27017
      - repl3.myapp.com:27017
    database: mongoid
    options:
      read: :secondary

Sharding

If you are using Mongoid in a sharded MongoDB environment and want to tell Mongoid to include the shard keys in its updates, specify this at the model class level.

class Person
  include Mongoid::Document

  field :first_name, type: String
  field :last_name, type: String

  shard_key :first_name, :last_name
end

In your mongoid.yml, just ensure that you are pointed at the mongos server in your hosts.

sessions:
  default:
    hosts:
      - mongos.myapp.com:27017
    database: mongoid
    options:
      read: :secondary