Working with Mongo

Annotations

In order to use Spindle structs with Mongo, they must have the required Mongo annotations.

  • mongo_collection - name of the Mongo collection
  • mongo_identifier - name of the Mongo instance

There are also a number of optional Mongo annotations:

  • primary_key - the name of the primary key field
  • foreign_key - one or more annotations with names of foreign key fields
  • index - one or more annotations with indexed fields

Example:

struct Checkin {
  1: optional ids.CheckinId id (wire_name="_id")
  2: optional ids.UserId userId (wire_name="uid")
  2: optional ids.VenueId venueId (wire_name="venueid")
} (primary_key="id",
   foreign_key="userId",
   foreign_key="venueId",
   index="userId: asc",
   index="venueId: asc",
   mongo_collection="checkins",
   mongo_identifier="foursquare")

Rogue Queries

There are two main differences between Lift Record and Spindle when it comes to creating and executing Rogue queries. First, queries are not created by calling Rogue methods on a model. Queries must be created explicitly by wrapping a model in a SpindleQuery (which we recommend aliasing to Q). Second, queries are not executed by called an execution method on the query, the query must be sent to a SpindleDatabaseService object to execute it.

For example:

import com.foursquare.rogue.spindle.{SpindleQuery => Q}
import com.foursquare.rogue.spindle.SpindleRogue._

val q = Q(Checkin).where(_.userId eqs 646).and(_.photoCount > 0)
val checkins = db.fetch(q)

Here is a basic SpindleDatabaseService implementation:

import com.foursquare.rogue.spindle.{SpindleDBCollectionFactory, SpindleDatabaseService}
import com.foursquare.spindle.UntypedMetaRecord
import com.mongodb.{DB, Mongo, MongoClient, MongoURI}

object db extends SpindleDatabaseService(ConcreteDBCollectionFactory)

object ConcreteDBCollectionFactory extends SpindleDBCollectionFactory {
  lazy val db: DB = {
    val mongoUrl = System.getenv("MONGOHQ_URL")
    if (mongoUrl == null) {
      // For local testing
      new MongoClient("localhost", 27017).getDB("mydatabase")
    } else {
      // Connect using the MongoHQ connection string
      val mongoURI = new MongoURI(mongoUrl)
      val mongo = mongoURI.connectDB
      if (mongoURI.getUsername != null && mongoURI.getUsername.nonEmpty) {
        mongo.authenticate(mongoURI.getUsername, mongoURI.getPassword)
      }
      mongo
    }
  }
  override def getPrimaryDB(meta: UntypedMetaRecord) = db
  override def indexCache = None
}