How to connect to a MongoDB database and insert data with Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 16.3, “How to connect to MongoDB and insert data with Scala.”

Problem

You want to use the MongoDB database with a Scala application, and want to learn how to connect to it, and insert and retrieve data.

Solution

If you don’t already have a MongoDB installation, download and install the MongoDB software per the instructions on its website. (It’s simple to install.) Once it’s running, use the Casbah driver with your Scala application to interact with MongoDB.

In development, I start my test instance of MongoDB from its installation directory with this command:

$ bin/mongod -vvvv --dbpath /Users/Al/data/mongodatabases

This starts the MongoDB server in a verbose mode, using the directory shown for its databases. After a lot of output, the last few lines from the mongod command look like this:

Sun Sep 16 14:27:34 [websvr] admin web console waiting for connections on port 28017
Sun Sep 16 14:27:34 [initandlisten] waiting for connections on port 27017

To demonstrate Casbah, build a small application. First, create a simple SBT project directory structure, as demonstrated in Recipe 18.1, “Creating a Project Directory Structure for SBT”.”

You can follow along by cloning my GitHub project.

Second, create your build.sbt file, specifically including the Casbah driver dependency:

name := "MongoDBDemo1"

version := "1.0"

scalaVersion := "2.10.0"

libraryDependencies ++= Seq(
    "org.mongodb" %% "casbah" % "2.6.0",
    "org.slf4j" % "slf4j-simple" % "1.6.4"
)

scalacOptions += "-deprecation"

The SLF4J library shown isn’t necessary for a simple example, but including it gets rid of a few warning messages.

Next, put the following code in a file named MongoFactory.scala in the root directory of your SBT project:

import com.mongodb.casbah.MongoCollection
import com.mongodb.casbah.MongoConnection

object MongoFactory {
    private val SERVER = "localhost"
    private val PORT   = 27017
    private val DATABASE = "portfolio"
    private val COLLECTION = "stocks"
    val connection = MongoConnection(SERVER)
    val collection = connection(DATABASE)(COLLECTION)
}

This object helps to simplify the interactions with a MongoDB database. You won’t need all of its functionality for this recipe, but it will be used completely in other recipes. If your MongoDB instance is running on the default port on localhost, those settings will work fine. If you already have a database named portfolio, be sure to use a different name.

Next, put the following code in a file named Common.scala, also in the root directory of your SBT project:

import com.mongodb.casbah.Imports._

case class Stock (symbol: String, price: Double)

object Common {
  /**
   * Convert a Stock object into a BSON format that MongoDb can store.
   */
  def buildMongoDbObject(stock: Stock): MongoDBObject = {
      val builder = MongoDBObject.newBuilder
      builder += "symbol" -> stock.symbol
      builder += "price" -> stock.price
      builder.result
  }
}

That code includes a simple case class to represent a Stock, and the buildMongoDbObject method in the Common object does the work of converting a Stock into a MongoDBObject that can be stored in a MongoDB database. The method converts the fields in the Stock object into key/value pairs that correspond to the MongoDB “document” paradigm. The MongoDBObject from the Casbah driver simplifies the conversion process.

With this code in place, it’s time to create a simple test program to insert several Stock instances into the database. Put the following code into a file named Insert.scala in the root directory of your SBT project:

import com.mongodb.casbah.Imports._
import Common._

object Insert extends App {

    // create some Stock instances
    val apple = Stock("AAPL", 600)
    val google = Stock("GOOG", 650)
    val netflix = Stock("NFLX", 60)

    // save them to the mongodb database
    saveStock(apple)
    saveStock(google)
    saveStock(netflix)

    // our 'save' method
    def saveStock(stock: Stock) {
        val mongoObj = buildMongoDbObject(stock)
        MongoFactory.collection.save(mongoObj)
    }

}

The interesting part of this code is the saveStock method. It does the following work:

  • It takes a Stock object as an input parameter.
  • It converts the Stock object to a MongoDBObject with the buildMongoDbObject method.
  • It saves the mongoObj object to the database collection with the save method of the collection instance. The collection is an instance of MongoCollection, which is obtained from the MongoFactory.

With everything in place, run this object with sbt run, and it will quietly insert the data into the collection.

Discussion

In Recipe 16.5, “Searching a MongoDB Collection”, you’ll see how to search a MongoDB collection using Scala and Casbah, but for the time being, if you open up the MongoDB command-line client and switch to the portfolio database, you can see the new documents in the stocks collection.

To do this, move to your MongoDB installation bin directory, start the mongo command-line client, move to the portfolio database, and list all the documents in the stocks collection, using these commands:

$ mongo
> use portfolio
> db.stocks.find()
{"_id" : ObjectId("5023fad43004f32afda0b550"), "symbol" : "AAPL", "price" : 600 }
{"_id" : ObjectId("5023fad43004f32afda0b551"), "symbol" : "GOOG", "price" : 650 }
{"_id" : ObjectId("5023fad43004f32afda0b552"), "symbol" : "NFLX", "price" : 60 }

This shows the three objects the Insert application inserted. You can remove those objects with the following command if you’d like to modify and run the program again:

> db.stocks.remove()

To help you work with MongoDB, I’ve created a Scala + MongoDB + Casbah example project on GitHub that includes the source code shown in this recipe, as well as additional code from the Find, Update, and Delete recipes in this chapter.

See Also