Compose MongoDB

This add-on is operated by Compose

Hosted, optimized and super-fast MongoDB databases.

Compose MongoDB

Last Updated: 18 May 2015

database java mongodb nosql

Table of Contents

MongoDB is a document-oriented data store. For more information about MongoDB, visit: http://www.mongodb.org.

Compose, formerly MongoHQ, is a cloud-based hosted database solution that allows developers to easily deploy, manage and scale both single and replica set MongoDB databases for their web and mobile applications. Our fast and reliable databases allow you to focus on developing your app while our team focuses on making your database fast and highly available.

Adding a Compose database

To add a Compose database to your Heroku application (using your console), simply install the Compose Add-on, specifying the plan that you desire. For example:

You can also add a Compose database if you are logged into the Heroku web site. Click on “Add-on Resources” for your app and select the plan you would like to use.

$ heroku addons:create mongohq:ssd_1g_elastic

This command provisions an Elastic Deployment and preallocates resources for a 1GB database on the Compose platform and updates your Heroku configs with an environment variable called MONGOHQ_URL. This variable will be assigned a connection string which includes all your server information as well as automatically-generated user/pass authentication to your database.

The environment variable and string will look like:

MONGOHQ_URL: mongodb://<user>:<pass>@candidate.15.mongolayer.com:10001,candidate.16.mongolayer.com:10001/app003132345

Now, you can use the MONGOHQ_URL variable in code and configurations for your driver, depending on the language you app is created in, connecting and authenticating to your MongoDB database hosted with Compose. We provide some examples of the use of this variable in the topics to follow.

Most of the various languages have an “official” driver as well as ORMs (Object-Relational Mappers) that you can use, depending on the type of implementation that you would like. This documentation will try to cover the most popular of each of these.

Use with Ruby

You will only need the mongo gem to get started. For optimal performance, you can include the bson_ext gem as well. From console, make sure the following drivers are installed:

$ gem install mongo
$ gem install bson_ext
require 'mongo'

mongohq_url = ENV['MONGOHQ_URL']
client = Mongo::Client.new(mongohq_url);
db = client.database
db.collection_names.each{|name| puts name }

This example will display a list of collections within the defined database specified in your MONGOHQ_URL

For more information about the Mongo Ruby Driver and its capabilities, visit: http://api.mongodb.org/ruby/current/

Mongoid (Ruby/MongoDB ORM)

Mongoid is an extremely popular Object-Document Mapper (ODM) created for the Ruby and MongoDB community. It benefits from wide adoption as well as solid community support. It is the tool of choice for the developers at Compose as well.

Mongoid has main versions now … 2.x and 3.x. The 2.x versions are in wide use, while the 3.x versions are slowly being incorporated into applications. For now, we will include documentation for both.

Mongoid 2.x

First things first … make sure that you have the right gem installed.

We’re big fans of Bundler, so even though we don’t include Bundler syntax here, feel free to use it. :)

$ gem install mongoid -v 2.4.12

Now that the gem is installed, the next step is to configure Mongoid to work with your Compose database provisioned through Heroku. Mongoid uses a YAML file to achieve this. Add a mongoid.yml file to your application. If this is Rails, it is normally stored in the config directory of your app.

Your mongoid.yml should look like:

production:
  uri: <%= ENV['MONGOHQ_URL'] %>

That’s it. Pretty simple.

There are additional configuration options that are available. We recommend a configuration that uses the following options:

persist_in_safe_mode turns on “safe writes” for the driver. In general, this is best practice.

production:
  uri: <%= ENV['MONGOHQ_URL'] %>
  max_retries_on_connection_failure: 20
  persist_in_safe_mode: true
  skip_version_check: true

This should get you fully connected. From here, its up to you to learn about MongoDB and the Mongoid driver. Full documentation for Mongoid 2.x is located here: http://two.mongoid.org/.

If you are using Mongoid 3.x and Moped on Heroku, make sure your app is upgraded to Ruby 1.9.3 and utilizing the Cedar Celedon stack.

Mongoid 3.x

Ensure that you have the mongoid gem installed … not declaring the version will make sure that you have the latest 3.x release of the code.

$ gem install mongoid

Now that the gem is installed, the next step is to configure Mongoid to work with your Compose database provisioned through Heroku. Mongoid uses a YAML file to achieve this. Add a mongoid.yml file to your application. If this is Rails, it is normally stored in the config directory of your app.

Your mongoid.yml should look like:

Check out the Mongoid 3.x documentation for more information about the new “sessions” syntax and how it is used.

production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>

That’s it. To learn more about sessions, please review the Mongoid 3.x documentation.

There are additional configuration options that are available through mongoid. We recommend a configuration that uses the following options:

production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>
      options:

This should get you fully connected. From here, its up to you to learn about MongoDB and the Mongoid driver. Full documentation for Mongoid 3.x is located here: http://www.mongoid.org/.

Mongoid and replica sets

Mongoid actually makes configuring replica sets quite easy … one of the cleanest implementations of all the drivers. It, of course, all happens in the mongoid.yml file.

Currently, when a replica set is deployed through the Add-on, it does not include both members of the set, only the member0. Therefore, you have to parse your MONGOHQ_URL or hard-code each member into your mongoid.yml file.

Here is how a typical mongoid.yml file for Mongoid 2.x would look:

As noted, in this example (and the below Mongoid 3.x example), you will need to parse out your MONGOHQ_URL Heroku config variable. Check out the get_connection method in the earlier Ruby example for tips on how to do this.

production:
  hosts:
    - - <hostname>.member0.mongohq.com
      - <port_number>
    - - <hostname>.member1.mongohq.com
      - <port_number>
  username: <username>
  password: <password>
  database: <database_name>
  max_retries_on_connection_failure: 20
  persist_in_safe_mode: true
  skip_version_check: true

With both of these configurations, we have “safe mode” turned on. Slower performance, but it will throw an error if it cannot write. Alter this for what suits you best.

Here is how a typical mongoid.yml file for Mongoid 3.x would look:

production:
  sessions:
    default:
      hosts:
        - - <hostname>.member0.mongohq.com
          - <port_number>
        - - <hostname>.member1.mongohq.com
          - <port_number>
      username: <username>
      password: <password>
      database: <database>
      options:
        skip_version_check: true
        safe: true

The big thing to note from this documentation is that all that changes are the member0 and member1 in the host names. The ports remain the same as well as the remainders of the connection strings.

MongoMapper (Ruby/MongoDB ORM)

MongoMapper (created by John Nunemaker of Github) is, similar to Mongoid, an Object Mapper. However, that is where the similarity ends. If you enjoy the comfort and syntax that ActiveRecord affords you, then MongoMapper will closely match that experience. When MongoDB was first on the scene, MongoMapper became quite popular for this reason.

It is important to remember that MongoMapper acts like a replacement to ActiveRecord. Given that, you need to change a couple of configurations to how a standard Rails app works.

To get started with MongoMapper and Rails 3, do the following:

First, update your config/application.rb from:

   require 'rails/all'

to

  require "action_controller/railtie"
  require "action_mailer/railtie"
  require "active_resource/railtie"
  require "rails/test_unit/railtie"
  # Uncomment for asset pipelining in Rails 3.1
  # require "sprockets/railtie"

Now, the next step is to add MongoMapper to your Gemfile and run bundle install.

  gem 'mongo_mapper'
  gem 'bson_ext'

Finally, you’ll need some configuration information. To generate config/mongo.yml, do this:

script/rails generate mongo_mapper:config

Now that all your configuration is proper, you need to connect your Compose database to your Rails app. Doing this is easy with your mongo.yml file. Change your settings to:

  production:
    uri: <%= ENV['MONGOHQ_URL'] %>

That’s it. You should be ready to go. One more MongoMapper-specific change that you may want to consider is configuring the Rails Model generator to work with MongoMapper. To do this, add the following inside the Application class of your config/application.rb.

  config.generators do |g|
    g.orm :mongo_mapper
  end

If you are interested in learning more about MongoMapper before fully integrating it into your application, check out the MongoMapper Console, as it provides a great way to discover more about MongoMapper.

Finally, while it is a bit dated now, you can still view Ryan Bates' screencast called MongoDB and MongoMapper if you are interested in a step-by-step guide. As you can imagine, some of the functionality in this video is deprecated by now.

Full documentation for MongoMapper is located here: http://mongomapper.com/.

Use with Java

MongoDB offers a standard Java client. In order to use this client in your project, you have to declare the dependency in your build and initialize the connection from the environment variable that we highlighted in the Adding a Compose Database section above.

Add the Mongo Java driver to your pom.xml

Add the following dependency to your pom.xml:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.7.2</version>
</dependency>

Use MongoDB in your application

URI mongoURI = new URI(System.getenv("MONGOHQ_URL"));

MongoURI mongoURI = new MongoURI(System.getenv("MONGOHQ_URL"));
DB db = mongoURI.connectDB();
db.authenticate(mongoURI.getUsername(), mongoURI.getPassword());

//Use the db object to talk to MongoDB
Set<String> colls = db.getCollectionNames();

Using MongoDB with Spring

Use the following Java Configuration class to set up a DB object as a singleton Spring bean:

@Configuration
public class SpringConfig {
    @Bean
    public DB getDb() throws UnknownHostException, MongoException {
        MongoURI mongoURI = new MongoURI(System.getenv("MONGOHQ_URL"));
        DB db = mongoURI.connectDB();
        db.authenticate(mongoURI.getUsername(), mongoURI.getPassword());

        return db;
    }
}

or the following XML configuration file:

MethodInvokingFactoryBean is used to initialize beans using methods other than constructors and setters.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
    <context:property-placeholder/>

    <bean id="mongoURI" class="com.mongodb.MongoURI">
      <constructor-arg value="${MONGOHQ_URL}"/>
    </bean>

    <!-- create db object by calling getDB on mongo bean -->
    <bean id="db" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
      <property name="targetObject"><ref local="mongoURI"/></property>
      <property name="targetMethod"><value>connectDB</value></property>
    </bean>

    <!-- call authenticate on db object -->
    <bean id="authenticateDB"
        class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject"><ref local="db" /></property>
        <property name="targetMethod">
            <value>authenticate</value>
        </property>
        <property name="arguments">
            <list>
                <value>#{ @mongoURI.getUsername() }</value>
                <value>#{ @mongoURI.getPassword() }</value>
            </list>
        </property>
    </bean>
</beans>

Sample code

To see a complete, working example, check out the sample code in github. The readme explains more about the example.

Compose replica sets

Compose provides multi-zone data redundancy and availability through MongoDB Replica Sets. Currently, when Heroku generates the configs for a replica set database, it does not include the connection strings for both members. So, this requires a bit of handling on the part of the developer to ensure configurations and high-availability are truly available in their app.

In your configs, if you deploy a replica set plan, the primary member is normally included. However, there is also a secondary member of the set as well and you need to make sure that your drivers are aware of it. While some drivers can auto-detect all the members of a set, they still need the full listing of members in their configuration.

If you need more assistance with this, please let us know.

Driver differences for replica sets

Please note that most drivers have very different configurations for replica sets. We will do our best, in this documentation, to highlight these differences, but make sure

Testing high availability

Once you have your driver settings for your replica set correct, but would like to simulate step downs to test the resiliency of your application, please let us know at: support@compose.io. We are happy to schedule some time with you to walk through these tests. This way, you feel confident that, in the event of an issue, your database will remain available and online.

Compose web tools

Compose provides helpful web tools that allow to you query and interact with the data stored in your MongoDB database. To access your database using our web tools, we nave provided integration with your Heroku log in, allowing you to access our app using your Heroku credentials. To do this, you will need to:

  1. Log into your Heroku account.
  2. Once logged in, click on the appropriate app.
  3. Click on the dropdown labled “Add-Ons” in the top-right of the screen.
  4. Select Compose.

Now that you are logged in, you can run queries, build indexes, add users, etc.

Upgrading your database

Heroku allows for only one database to be associated with each provisioned application on their platform. Therefore, since we actually move your data and update your connection string, the current upgrade process for non-replica-set databases requires a maintenance window to allow you move data from one database to another.

This exercise will only work if you have MongoDB installed on your local machine. If you need help, just ask!

To do this, use the following instructions. In this example, we will upgrade from a “sandbox” to a “ssd_1g_elastic” database.

Please note: You will need your current MONGOHQ_URL (from your Heroku configs) available before you begin as the following steps will alter it permanently.

Take your application into maintenance mode.

$ heroku maintenance:on

Run a mongodump of your current database.

$ mongodump -h hostname.mongohq.com:port_number -d database_name -u username -p password -o /path/on/my/local/computer

Deprovision the old database for this app, making sure that the mongodump in Step #2 completed successfully.

$ heroku addons:destroy mongohq:sandbox

Provision a new database for this app.

$ heroku addons:create mongohq:ssd_1g_elastic

Make available the newly updated MONGOHQ_URL from your Heroku configs.

Run a mongorestore of your locally backed up database to your new database (updating your connection info.)

$ mongorestore -h hostname.mongohq.com:port_number -d database_name -u username -p password /path/on/my/computer/to/mongodump/db_name

Return from maintenance mode.

$ heroku maintenance:off

At this point, everything should be good. If you were properly relying on the MONGOHQ_URL in your application, then it should automatically reflect the changed database and everything should be working properly.

If you need any help in this process, please contact us. We are happy to assist.

Backups

We take (and maintain) daily snapshots of all databases hosted on the Compose platform. Sandbox accounts do not include backups.

What if I have an issue?

If there is ever a serious issue or error and you need assistance, please contact Compose Support at: support@compose.io. It is most helpful if you include the full MONGOHQ_URL in your Heroku configs when you send us a note. That will ensure that we can act swiftly to restore data.

Help!

Common Issues

All the sudden, I can’t authenticate to my database? Wat!

If your app can no longer authenticate to your database, it may mean that your system.users collection has been erased by a rake task. For example. if you run a task like rake db:reseed in Mongoid, it will remove database collections, including your system users. This will make you sad.

You can add a database user back by using the Compose web UI (accessed through your app in Heroku) or reach out to us at support@compose.io and we can assist in recovering the users for you.

The password that the Compose web tools displays is not working for me.

If you copied the displayed password in the MongoHQ web tools into your app, the authentication will fail because the web tools are actually displaying the hashed value of your password and not your actual password.

The password to your database was automatically created when you provisioned your Compose database through Heroku. You can either use the MONGOHQ_URL in the uri value in your MongoDB driver configs or access your user name and password by running the following in your console:

  heroku config | grep "MONGOHQ"

Support

At Compose, we have a talented and friendly team and are always happy to support you as you develop with Heroku and MongoDB. Feel free to reach out to us at: support@compose.io. Make sure to include the name of your database … it is your appID name.

Status Monitoring

For support requests, please contact Heroku Support using http://support.heroku.com. For status monitoring, please check Heroku Status at: http://status.heroku.com or Compose Status at https://status.compose.io.

Additional documentation

Additional documentation, covering other topics about Compose (as well as MongoDB) can be located at: https://docs.compose.io.