An Introduction to Mongoid for Users of ActiveRecord,
by Emily Giurleo
In the past 15 years, document databases such as MongoDB have become increasingly stable and sophisticated, and thus increasingly popular. While many engineers may be curious about document databases, learning new tools can seem intimidating and time-consuming. Luckily, this doesn’t have to be the case. This talk will provide an introduction to Mongoid — the MongoDB Object-Document Mapper for Rails — by demonstrating Mongoid’s most commonly-used APIs along with side-by-side examples from ActiveRecord, as well as a discussion on the benefits and drawbacks of each of these two frameworks.
In this talk, I will introduce the audience to Mongoid, MongoDB's Object-Relational Mapper for Ruby on Rails. I will explain how to accomplish common tasks by presenting examples of commonly-used Mongoid APIs alongside analagous examples using ActiveRecord. By the end of the talk, the audience will know how to create a database schema with validators, callbacks, and relations, perform CRUD operations, set callbacks, migrate data, ensure the integrity of their data using transactions, and improve the performance of their app using indexes and sharding. The goal of this talk is to build the viewer’s confidence in a new tool, not to pitch Mongoid as a replacement for ActiveRecord.
This talk is intended for beginner to intermediate Rails engineers who are familiar with ActiveRecord and unfamiliar with document databases. To ensure the accessibility of the talk, I plan to define any concepts with which a junior engineer might be unfamiliar, such as database indexes, transactions, and sharding.
- What is MongoDB?
- MongoDB is a document database.
- A document database is a set of “collections” (analogous to tables), where each collection contains many “documents” (analogous to rows). Each document is a series of key-value pairs (essentially a JSON object).
- Why would you choose to build a project with MongoDB rather than SQL?
- You do not need to run migrations to create and update schemas in MongoDB, which increases the speed at which you can iterate.
- Document data structure is well-suited to denormalized data.
- MongoDB and its associated libraries have native support for database sharding and a variety of indexing features, which make it easy to improve performance.
- Preview of talk:
- I will demonstrate how to set up a Rails app with Mongoid and point out the major differences between that app and an app set up with the postgres ORM.
- I will demonstrate common Mongoid APIs, such as defining schemas and querying the database, using side-by-side comparisons with ActiveRecord.
- I will use these comparisons to point out the tradeoffs between these two frameworks and reinforce my points about the benefits of using Mongoid in certain scenarios.
Setting up a Rails app
- What is Mongoid?
- Mongoid is the official MongoDB Object-Document Mapper (map documents stored in MongoDB to Ruby objects).
- Point out the differences in setting up a Rails app for MongoDB vs. PostgreSQL
- Setting up Rails with these two frameworks is going to be fairly similar, which should enforce the point that Mongoid is a usable framework.
- I will point out small differences in configuration between the two ORMs and explain those differences.
- Demonstrate how to create Rails models using ActiveRecord and Mongoid.
- For ActiveRecord, you must generate a migration, fill the migration with information about your new schema, and then run the migration.
- For Mongoid, you create a new model file and define the schema class in that file. There are no migrations.
- What is a schema in Mongoid?
- A schema defines the way that you can interact with an object in the Ruby layer. Defining a schema creates methods on your class (for example: accessors and mutators), but does not enforce any restrictions on the underlying database documents (i.e. defining a field on the schema does not mean a document has to have that field).
- Data types: briefly discuss the value types defined by MongoDB and how those map to data types found in SQL databases.
Create, Read, Update, Delete (CRUD)
- These are the primary means of putting data in and getting data out of the database.
- Do a side-by-side comparison of CRUD operations for Mongoid and ActiveRecord.
- These are going to be pretty similar. This should be a familiar touchpoint to make sure that the audience understands how to interact with the schemas from the previous section.
- Clarify the relationship between Mongoid schemas and the structure of underlying documents. You can update documents to have fields not defined in your schema. You can change the schema such that previously-defined fields are no longer defined. This does not change the underlying document, only the way that document is represented as a Ruby object.
Schemas, in depth
- Much like ActiveRecord, Mongoid allows you to define relations (called “associations”) between models: has_one, has_many, belongs_to, has_and_belongs_to_many. Show how to set up such associations using an ActiveRecord migration and a Mongoid schema change.
- MongoDB does not have joins. Explain how has_and_belongs_to_many works on the database level for ActiveRecord and MongoDB.
- MongoDB has “embedded associations” -- when one document contains another document of a different type. Talk about scenarios that warrant the use of this pattern (denormalization of data).
- A caveat: MongoDB has weaker referential integrity than a traditional SQL database. Demonstrate some scenarios in which data can become inconsistent if the user is not careful.
- You can use validations and callbacks (Mongoid uses ActiveModel validations and callbacks) to enforce some referential integrity at the application-level. (I may expand more on this if I have time for it.) Validations and Callbacks
Transactions: mention that MongoDB offers multi-document ACID transactions and briefly show a side-by-side comparison of
Performance and Scaling
- What is an index?
- How do you add indexes to your schemas in ActiveRecord and Mongoid, and what happens on the database level when you do so?
- Demonstrate creating an index with Mongoid, which involves adding a line to your schema and then running a rake task.
- Mention some nicer MongoDB index features, such as sparse indexes, creating indexes in the background, and geospatial indexes.
- Sharding: mention that MongoDB makes it easy to support sharding with a one-line change to your Mongoid schema and a Rake task.
Migrations: a brief discussion on how to run a “migration” using Mongoid. For example, you could use a Rake task or a script along with a common queue-ing framework. Unlike with ActiveRecord, you must write out the entire migration, but it does allow for more flexibility.
Conclusion: The main takeaway is that different tools are suitable for different tasks. Reiterate when members of the audience might benefit from using Mongoid vs. ActiveRecord.
According to db-engines.com, document databases such as MongoDB, Couchbase, and Amazon DynamoDB are more popular than ever. With benefits such as quicker iteration, an intuitive way to denormalize data, and ease of scaling, document databases can be a useful addition to an engineering organization’s stack or even a single developer’s personal project. I have personally been a user of MongoDB and Mongoid for over three years, and I am now a contributor to Mongoid and the MongoDB Ruby Driver. When I speak to other Rubyists about my experience, I often receive two questions: what are the benefits of using MongoDB, and how easy is it to adopt in a Rails application? The goal of my talk is to answer those two questions using side-by-side examples from ActiveRecord as a way of building understanding and providing concrete evidence to back up my claims.
The goal of this talk is not to pitch Mongoid as a replacement for ActiveRecord. I often quote the well-known saying, “When all you have is a hammer, everything looks like a nail.” If you only know how to use one type of database engine, you are forced to live with the limitations of that system. Intead, I would encourage people to learn how to use new tools, to understand the benefits and drawbacks of those tools, and to recognize the scenarios in which those tools are appropriate and helpful.