Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

Referenced Associations

Associations in Mongoid allow you to create relationships between models. In this guide, you can learn how referenced associations allow you to create a relationship between two models where one model references the other. Mongoid supports the following referenced association types:

  • has_one

  • has_many

  • belongs_to

  • has_and_belongs_to_many

The following sections describe how to use each of these association types.

You can use the has_one macro to declare that documents represented by one class also contain a document represented by a separate child class. The following example creates a Band class with a has_one relationship to a Studio class:

class Band
include Mongoid::Document
has_one :studio
end

When you declare a has_one association, the child class must also use the belongs_to association that references the parent class. The following example shows the Studio class referenced in the preceding Band class:

class Studio
include Mongoid::Document
belongs_to :band
end

To learn more about the belongs_to macro, see the Belongs To section.

You can use validations to ensure that the child class is present in your parent class, as shown in the following example:

class Band
include Mongoid::Document
has_one :studio
validates_presence_of :studio
end

To learn more about validations in Mongoid, see the Validations guide.

You can use the has_many macro to declare that documents represented by a class contain multiple child documents represented by another class. The following example creates a Band class with a has_many relationship to a Members class:

class Band
include Mongoid::Document
has_many :members
end

When you declare a has_many association, the child class must also use the belongs_to association that references the parent class. The following example shows the Member class referenced in the preceding Band class:

class Member
include Mongoid::Document
belongs_to :band
end

To learn more about the belongs_to macro, see the Belongs To section.

You can use validations to ensure that the child class is present in your parent class, as shown in the following example:

class Band
include Mongoid::Document
has_many :members
validates_presence_of :members
end

To learn more about validations in Mongoid, see the Validations guide.

You can use the any? method on a has_many association to determine if the association contains any documents without retrieving the entire set of documents from the database.

The following example uses the any? method to determine if documents in the Band class contain any Members documents:

band = Band.first
band.members.any?

You can also use the any? method with a filter to find documents that match a specified criteria, as shown in the following example:

band = Band.first
band.members.any? { |member| member.instrument == 'piano' }

You can supply a class name to the any? method to filter the results by the name of the class. This is useful for polymorphic associations:

class Drummer < Member
end
band = Band.first
band.members.any?(Drummer)

Note

After the data of the associated class is loaded to Mongoid, subsequent calls to the any? method do not query the database. Instead, Mongoid uses the data that is already loaded in memory.

You can also call the exists? method to determine if there are any persisted documents in the association. The exists? method always queries the database and checks only for documents that have been saved to the database. The exists? method does not allow for filtering and does not accept any arguments.

The following example uses the exists? method to determine if there are any persisted Members documents in the Band class:

band = Band.create!
# Member is not persisted.
band.members.build
band.members.exists?
# Outputs: false
# Persist the member
band.members.map(&:save!)
band.members.exists?
# Outputs: true

Use the belongs_to macro to declare that a document represented by one class is a child of a document represented by another class. By default, the _id field of the parent class is stored in the child class. The following example creates a Members class with a belongs_to association to a Band class:

class Members
include Mongoid::Document
belongs_to :band
end

You can allow Mongoid to persist documents to the database without storing the _id of the associated parent class by setting the optional option to true, as shown in the following example:

class Members
include Mongoid::Document
belongs_to :band, optional: true
end

Tip

You can globally change the default behavior of the belongs_to association to not require their parent class by setting the belongs_to_required_by_default configuration option to false in your application's configuration settings.

You can specify a belongs_to association in a child class without specifying a matching has_one or has_many association in the parent class. When doing so, you can't access the fields of the child document from the parent class, but you can access the parent fields that are stored in the child class, such as the parent's _id field. In the following example, the Band class cannot access the Members class, but the Members class can access the Band class:

class Band
include Mongoid::Document
end
class Members
include Mongoid::Document
belongs_to :band
end

For clarity, you can optionally set the inverse_of option to nil to indicate that the parent class does not contain a has_one or has_many association to the child class, as shown in the following example:

class Band
include Mongoid::Document
end
class Members
include Mongoid::Document
belongs_to :band, inverse_of: nil
end

Use the has_and_belongs_to_many macro to declare that a class model contains a many-to-many relationship with another class. In a many-to-many relationship, each document in one class can be associated with multiple documents in another class. The following example creates a Band class with a has_and_belongs_to_many relationship to a Members class. A Band document can reference multiple Members documents, and a Members document can reference multiple Band documents.

class Band
include Mongoid::Document
has_and_belongs_to_many :members
end
class Members
include Mongoid::Document
has_and_belongs_to_many :bands
end

When you declare a has_and_belongs_to_many association, both model instances store a list of the associated document's _id values. You can set the inverse_of option to nil to store the associated document's _id values in only one of the model instances. The following example prompts Mongoid to store the associated document's _id values in only the Band class:

class Band
include Mongoid::Document
has_and_belongs_to_many :tags, inverse_of: nil
end
class Tag
include Mongoid::Document
end

Tip

When you update a document that has a has_and_belongs_to_many association, Mongoid sets the updated_at field of updated document but does not set the updated_at field of the associated documents.

You can use an aggregation pipeline to query for documents across referenced associations. The aggregation pipeline allows you to create queries across multiple collections and manipulate data into a specified format. To learn more about using the aggregation pipeline, see the Aggregation guide.

For simple queries, you can query the association directly. When you directly query on a collection, you can query only on fields and values that are in the collection itself. You cannot directly query on collections associated to the one you are querying.

For example, consider the following Band and Tour classes:

class Band
include Mongoid::Document
has_many :tours
field :name, type: String
end
class Tour
include Mongoid::Document
belongs_to :band
field :year, type: Integer
end

The following example queries the Tour class for documents that have a year value of 2000 or greater and saves the band_id of those documents. It then queries the Band class for documents that have those band_id values.

band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
bands = Band.find(band_ids)

Back

Callbacks

On this page