Docs Menu

Docs HomeMongoid

Index Management

On this page

  • Specifying Indexes
  • Specifying Search Indexes on MongoDB Atlas
  • Index Management Rake Tasks
  • Managing Search Indexes on MongoDB Atlas
  • Telling Mongoid Where to Look For Models
  • Using Rake Tasks With Non-Rails Applications

You can define indexes on documents using the index macro. Provide the key for the index along with a direction. Additional options can be supplied in the second options hash parameter:

class Person
include Mongoid::Document
field :ssn
index({ ssn: 1 }, { unique: true, name: "ssn_index" })
end

You can define indexes on embedded document fields as well:

class Person
include Mongoid::Document
embeds_many :addresses
index "addresses.street" => 1
end

You can index on multiple fields and provide direction:

class Person
include Mongoid::Document
field :first_name
field :last_name
index({ first_name: 1, last_name: 1 }, { unique: true })
end

Indexes can be sparse:

class Person
include Mongoid::Document
field :ssn
index({ ssn: -1 }, { sparse: true })
end

For geospatial indexes, make sure the field being indexed is of type Array:

class Person
include Mongoid::Document
field :location, type: Array
index({ location: "2d" }, { min: -200, max: 200 })
end

Indexes can be scoped to a specific database:

class Person
include Mongoid::Document
field :ssn
index({ ssn: 1 }, { database: "users", unique: true, background: true })
end

You may use aliased field names in index definitions. Field aliases will also be resolved on the following options: partial_filter_expression, weights, wildcard_projection.

class Person
include Mongoid::Document
field :a, as: :age
index({ age: 1 }, { partial_filter_expression: { age: { '$gte' => 20 } })
end

Note

The expansion of field name aliases in index options such as partial_filter_expression is performed according to the behavior of MongoDB server 6.0. Future server versions may change how they interpret these options, and Mongoid's functionality may not support such changes.

Mongoid can define indexes on "foreign key" fields for associations. This only works on the association macro that the foreign key is stored on:

class Comment
include Mongoid::Document
belongs_to :post, index: true
has_and_belongs_to_many :preferences, index: true
end

Deprecated: In MongoDB 4.0 and earlier, users could control whether to build indexes in the foreground (blocking) or background (non-blocking, but less efficient) using the background option.

class Person
include Mongoid::Document
field :ssn
index({ ssn: 1 }, { unique: true, background: true })
end

The default value of background is controlled by Mongoid's background_indexing configuration option.

The background option has no effect as of MongoDB 4.2.

If your application is connected to MongoDB Atlas, you can declare and manage search indexes on your models. (This feature is only available on MongoDB Atlas.)

To declare a search index, use the search_index macro in your model:

class Message
include Mongoid::Document
search_index { ... }
search_index :named_index, { ... }
end

Search indexes may be given an explicit name; this is necessary if you have more than one search index on a model.

When you want to create the indexes in the database, use the provided db:mongoid:create_indexes Rake task:

$ rake db:mongoid:create_indexes

Mongoid also provides a Rake task to delete all secondary indexes.

$ rake db:mongoid:remove_indexes

Note: the output of these Rake tasks goes to the default logger configured by Rails. This is usually a file like log/development.log and not standard output.

These create/remove indexes commands also works for just one model by running in Rails console:

# Create indexes for Model
Model.create_indexes
# Remove indexes for Model
Model.remove_indexes

If you have defined search indexes on your model, there are rake tasks available for creating and removing those search indexes:

$ rake db:mongoid:create_search_indexes
$ rake db:mongoid:remove_search_indexes

By default, creating search indexes will wait for the indexes to be created, which can take quite some time. If you want to simply let the database create the indexes in the background, you can set the WAIT_FOR_SEARCH_INDEXES environment variable to 0, like this:

$ rake WAIT_FOR_SEARCH_INDEXES=0 db:mongoid:create_search_indexes

Note that the task for removing search indexes will remove all search indexes from all models, and should be used with caution.

You can also add and remove search indexes for a single model by invoking the following in a Rails console:

# Create all defined search indexes on the model; this will return
# immediately and the indexes will be created in the background.
Model.create_search_indexes
# Remove all search indexes from the model
Model.remove_search_indexes
# Enumerate all search indexes on the model
Model.search_indexes.each { |index| ... }

For non-Rails applications, Mongoid's rake tasks will look for models in ./app/models and ./lib/models. For Rails, Mongoid will look in ./app/models (or wherever you've configured Rails to look for models). If your models are in another location, you will need to tell Mongoid where to look for them with Mongoid.model_paths=. You can do this by setting it in your application's Rakefile:

# Rakefile
# keep the defaults, but add more paths to look for models
Mongoid.model_paths += [ "./src/models", "./lib/documents" ]
# or, override the defaults entirely
Mongoid.model_paths = [ "./src/models", "./lib/documents" ]

Make sure that these paths are in your application's load path, as well. For example:

# Rakefile
$LOAD_PATHS.concat [ "./src/models", "./lib/documents" ]

Mongoid's Rake tasks are automatically loaded in Rails applications using Mongoid. When using Mongoid with a non-Rails application, these tasks must be loaded manually:

# Rakefile
require 'mongoid'
load 'mongoid/tasks/database.rake'

If your application uses Bundler, you can require bundler/setup instead of explicitly requiring mongoid:

# Rakefile
require 'bundler/setup'
load 'mongoid/tasks/database.rake'
←  Collection ConfigurationSharding Configuration →