MongoMapper allows you to define the relationship between your models. When you define an association, MongoMapper creates methods on your model that make it easy to create, break, find, and persist the connections between models in your application.
Associations between models in MongoMapper are defined by combining the many
, belongs_to
, and one
methods. These three methods can form a one-to-many, many-to-many, or one-to-one association.
Use many
and belongs_to
in your models to form a one-to-many association.
In this one-to-many relationship, one tree can have many birds perching on it, and a bird can only be in one tree at a time.
In a relational database, you might model a many-to-many relationship by creating a “join table.” MongoDB doesn’t have joins. But because arrays are first class citizens in MongoDB, you can simply store an array of ObjectId’s.
Use an array key and many
with the :in
option in your model to form a many-to-many association.
Each book stores an array of the id’s of its authors in the author_ids
key. This allows books to have many authors, and authors to have many books.
Currently, many-to-many associations are one-sided in MongoMapper. Support will be added in the near future for the inverse.
Use one
and belongs_to
in your models to form a one-to-one association.
In this one-to-one relations, an employee can only use one desk, and each desk can only be used by one employee.
When one document will almost always be fetched with another, it makes sense to just embed it into the same document. many
and one
associations can be used with embedded models. See EmbeddedDocument for more information.
MongoMapper lets you define polymorphic associations where one side of the association won’t always be the same class. The polymorphism can be done either the basic way (polymorphic documents in many different collections) or using single collection inheritance (polymorphic documents in one collection). See the examples below.
Note: All of these polymorphic examples use the many
association, but MongoMapper’s polymorphism works fine with one
in place of many
.
Say you want users to be able to comment on articles and products:
In the database, MongoMapper adds an extra commentable_type
key so that it can fetch each comment’s parent from the proper collection.
In the database, a comment might look like this when converted to Ruby:
Polymorphism can also be provided by Single Collection Inheritance. The previous example could be rewritten:
Though you can’t have polymorphism on the belongs_to
side with the basic method, with SCI you can:
And SCI also allows many-to-many polymorphism, which also can’t be done the basic way. For example, here’s a richer model of books and authors:
Single collection inheritance is needed for polymorphism on the belongs_to
side and for many-to-many polymorphism because when MongoMapper looks for associated documents, it only fires one query on one collection—therefore all of an object’s children must be located in that one collection. On the other hand, with basic polymorphism the different document types are located in different collections.
Embedded documents may also be polymorphic. Both basic polymorphism and SCI polymorphism work fine for all embedded associations. Here’s one example:
MongoMapper stores the class name in a _type
key so the objects get loaded as the proper class. For example, a human in the database might look like this when converted to Ruby:
You can extend your core model associations to help you return variations on the associated objects, or encapsulate behavior related to the association.
If you want reuse an extension between many associations, define a module.
Sometimes you need access to the proxy owner or target objects in your extension. The following methods are available inside of your extension: