Provides simple serialization for ReactiveMongo - reactive, asynchronous and non-blocking Scala driver for MongoDB.
This started as a fork of Play-ReactiveMongo as it seemed like a good idea to refactor out the coupling to a Play application.
With some minimal effort, as the ReactiveMongo people had already done the majority of the work, we felt that adding a base repository class creates a library without some of the issues the other simpler libraries have.
Simple-reactivemongo uses Play Json to serialise/deserialise JSON to/from case classes and
there is a specialized collection called JSONCollection
that deals naturally with JSValue
and JSObject
instead of ReactiveMongo's BSONDocument
.
In your project/Build.scala:
libraryDependencies ++= Seq(
"uk.gov.hmrc" %% "simple-reactivemongo" % "1.1.0",
"com.typesafe.play" %% "play-json" % "2.2.3" //supports from 2.1.0
)
Create a case class
that represents to serialise to mongo.
Create JSON Read/Write converters. Or if you are doing nothing special create a companion object for the case class with an implicit member set by play.api.libs.json.Json.format[A]
Extend ResponsiveRepository which will provide you with some commonly used functionality.
If the repository requires any indexes override indexes: Seq[Index]
to provide a sequence of indexes that will be applied. Any errors will be logged should they fail.
If you prefer to drop the underscore for the 'id' field in the domain case class then wrap the domain formats in ReactiveMongoFormats.mongoEntity
case class TestObject(aField: String,
anotherField: Option[String] = None,
optionalCollection: Option[List[NestedModel]] = None,
nestedMapOfCollections: Map[String, List[Map[String, Seq[NestedModel]]]] = Map.empty,
modifiedDetails: CreationAndLastModifiedDetail = CreationAndLastModifiedDetail(),
jsValue: Option[JsValue] = None,
location : Tuple2[Double, Double] = (0.0, 0.0),
id: BSONObjectID = BSONObjectID.generate) {
def markUpdated(implicit updatedTime: DateTime) = copy(
modifiedDetails = modifiedDetails.updated(updatedTime)
)
}
object TestObject {
import ReactiveMongoFormats.{objectIdFormats, mongoEntity}
implicit val formats = mongoEntity {
implicit val locationFormat = TupleFormats.tuple2Format[Double, Double]
implicit val nestedModelformats = Json.format[NestedModel]
Json.format[TestObject]
}
}
class SimpleTestRepository(implicit mc: MongoConnector)
extends ReactiveRepository[TestObject, BSONObjectID]("simpleTestRepository", mc.db, TestObject.formats, ReactiveMongoFormats.objectIdFormats) {
import reactivemongo.api.indexes.IndexType
import reactivemongo.api.indexes.Index
override def indexes: Seq[Index] = Seq(
Index(Seq("aField" -> IndexType.Ascending), name = Some("aFieldUniqueIdx"), unique = true, sparse = true)
)
}
(See ReactiveRepositorySpec for example usage)
Built-in JSON converters (Formats) for often used types
Formats for BSONObjectId and Joda time classes are implemented (see ReactiveMongoFormats)
ReactiveMongo loads it's configuration from the key mongo-async-driver
To change the log level (prevent dead-letter logging for example)
mongo-async-driver {
akka {
loglevel = WARNING
}
}