Many of the application’s I’ve developed for myself and for clients over the recent years are intimately tied to MongoDB. This means that any new technology stack I experiment with need to be able to work well with this database.

Elixir is no exception to this rule.

Thankfully, Elixir and the Phoenix framework are database agnostic. They don’t require you to be tied to a single database, and even offer options for interfacing with a wide variety of databases.

Let’s dig into how we can use MongoDB in an Elixir application.

This article was written with version ~0.1 of the MongoDB driver in mind. For instructions on using version 0.2 of the MongoDB driver, see How to Use MongoDB with Elixir - Revisited.

Ecto Adapter

A very common way of interacting with a database in an Elixir application is to use the Ecto package.

Ecto acts as a repository layer around your database. It lets you write queries in a unified languages, and supports communicating with many types of databases through “adapters”.

The Mongo.Ecto package is the Ecto adapter for MongoDB. Unfortunately, Mongo.Ecto is currently in a state of flux.

Mongo.Ecto is currently incompatible with Ecto 1.1. On top of that, work to support Ecto 2.0 is very much a work in progress.

All of this is to say that integrating with MongoDB through Ecto is not currently an option if you’re looking for a low-friction, fully supported solution.

MongoDB Driver

Under the hood, the Mongo.Ecto adapter makes use of Eric Meadows-Jönsson’s MongoDB driver package.

While Mongo.Ecto is in a state of flux, the MongoDB driver package seems to be stable and functional.

Setting up the MongoDB driver in your Elixir application is a simple process. Get started by following the documentation on GitHub. Once you’ve defined your MongoPool module, you can start the process and make your queries:

{:ok, _} = MongoPool.start_link(database: "test")

|> Mongo.find("collection", %{ "foo" => "bar" })
|> Enum.to_list

Database options can be passed into the connection pool when you start_link. For example, to connect to a "meteor" database on localhost:3001, you could initiate your connection pool with these options:

{:ok, _} = MongoPool.start_link(database: "meteor", port: 3001)

You can find all available options in the Mongo.Connection module, or through iex:

iex -S mix
> h Mongo.Connection.start_link

Final Thoughts

It’s a shame that the Mongo.Ecto adapter isn’t in a stable state. While the MongoDB driver works beautifully, it would be nice to leverage the unified interface of Ecto when building applications.

When using the MongoDB driver directly, you need to concern yourself with tightly coupling your application to your persistence method. Ecto provides a nice layer of decoupling between the two.

Additionally, using the MongoDB driver directly opens yourself up to the possibility of being vulnerable to NoSQL injection attacks. We’ll drive into that topic next week.