What's new?
Synchronous:
import reactivemongo.api.{ DB, MongoConnection }def deprecatedDB(con: MongoConnection) = con.db("db_name")
DB
reference is immediately usableAsynchronous: Future[DB]
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.api.{ DB, MongoConnection }def newResolution(con: MongoConnection): Future[DB] = con.database("db_name")
primary
)acknowledged
)import reactivemongo.api._, commands.WriteConcerndef connection(driver: MongoDriver) = driver.connection(List("localhost"), options = MongoConnectionOptions( readPreference = ReadPreference.primary, writeConcern = WriteConcern.Acknowledged, failoverStrategy = FailoverStrategy(retries = 10) ) )
maxIdleTimeMS
(e.g. 2s)monitorRefreshMS
: frequency for pool monitor (e.g. 5s)import reactivemongo.api._MongoConnectionOptions( authMode = ScramSha1Authentication, // default SCRAM SHA1 maxIdleTimeMS = 2000 /* 2s */, monitorRefreshMS = 5000 /* check nodes each 5s */)
The collection API provides new operations.
Example findAndUpdate
: Find Joline and update her age to 35
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson._import reactivemongo.api.collections.bson.BSONCollectioncase class Person( firstName: String, lastName: String, age: Int)object Person { implicit def reader: BSONDocumentReader[Person] = Macros.reader[Person]}def example1(coll: BSONCollection): Future[Option[Person]] = coll.findAndUpdate( BSONDocument("name" -> "Joline"), BSONDocument("$set" -> BSONDocument("age" -> 35)), fetchNewObject = true ).map(_.result[Person])
Example findAndRemove
: Find document about Jack and remove it
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectiondef example2(coll: BSONCollection) = coll.findAndRemove(BSONDocument("name" -> "Jack"))
New requireOne
builder
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectiontrait PersonService { def collection: BSONCollection def example3(f: String, l: String): Future[Person] = collection.find(BSONDocument( "firstName" -> f, "lastName" -> l )).requireOne[Person]}
Option maxTimeMs
now supported
Example: Make MongoDB stop if find takes more than 1234ms
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectiondef example4(coll: BSONCollection) = coll.find(BSONDocument("foo" -> "bar")).maxTimeMs(1234L)
Operation explain
to get query plan.
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectiondef example5(coll: BSONCollection) = coll.find(BSONDocument.empty).explain().one[BSONDocument]
Pattern matching utilities for WriteResult
WriteResult.Code
: match by error codeWriteResult.Message
: match by error messageimport reactivemongo.api.commands.WriteResult def example6(res: WriteResult) = res match { case WriteResult.Code(11000) => println("Match the code 11000") // 11000 code for the Duplicate error case WriteResult.Message( "Must match this exact message") => println("Match the error message") case _ => ()}
Pattern matching utilities for CommandError
CommandError.Code
: match by error codeCommandError.Message
: match by error messageimport reactivemongo.api.commands.CommandError def example7(res: CommandError) = res match { case CommandError.Code(11000) => println("Match the code 11000") case CommandError.Message( "Must match this exact message") => println("Match the error message") case _ => ()}
GridFS
support provides operations with automatic MD5:saveWithMD5
& iterateeWithMD5
import scala.concurrent.{ ExecutionContext, Future }import play.api.libs.iteratee.Enumeratorimport reactivemongo.api._, gridfs._, Implicits._import reactivemongo.bson.BSONValuetype BSONFile = reactivemongo.api.gridfs. ReadFile[BSONSerializationPack.type, BSONValue]def example8( gridfs: GridFS[BSONSerializationPack.type], filename: String, typ: Option[String], data: Enumerator[Array[Byte]])(implicit ec: ExecutionContext): Future[BSONFile] = gridfs.saveWithMD5(data, DefaultFileToSave(Some(filename), typ)
Manipulate the BSON values and documents
{ _id: 1, MongoDB: "represents JSON documents", in: "binary-encoded format"}
BSONReader
New combinator afterRead
Example: Reader for MyEnum
based on the one for BSON string
import reactivemongo.bson._sealed trait MyEnumobject EnumValA extends MyEnumobject EnumValB extends MyEnumval underlying: implicitly[BSONReader[BSONString, String]]implicit def example9: BSONReader[BSONString, MyEnum] = underlying.afterRead { case "A" => EnumValA case "B" => EnumValB case v => sys.error(s"unexpected value: $v") }
BSONWriter
New combinator beforeWrite
Example: Writer to encode as BSON string the instances of MyEnum
import reactivemongo.bson._val underlying = implicitly[BSONWriter[String, BSONString]]implicit def example10: BSONWriter[MyEnum, BSONString] = underlying.beforeWrite[MyEnum] { case EnumValA => "A" case _ => "B" }
Support for sealed family
Example: Types family of Node
and Leaf
import reactivemongo.bson._sealed trait Treecase class Node(left: Tree, right: Tree) extends Treecase class Leaf(data: String) extends Treeval example11: BSONDocumentHandler[Tree] = Macros.handler[Tree]
Example: Find person documents and consume using an Akka Sink
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport akka.stream.Materializerimport akka.stream.scaladsl.{ Sink, Source }import reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectionimport reactivemongo.akkastream.{ State, cursorProducer }trait Example12 { implicit def m: Materializer def apply(coll: BSONCollection, query: BSONDocument) = { val sourceOfPeople = coll.find(query). cursor[BSONDocument].documentSource() sourceOfPeople.runWith(Sink.seq[BSONDocument]) }}
New streaming based on primitive Cursor.foldWhileM[A]
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.api.Cursordef example13(c: Cursor[String]): Future[List[String]] = c.foldWhile(List.empty[String], 1000/* max doc */)( { (ls, str) => // process next String value if (str startsWith "#") Cursor.Cont(ls) // Skip else if (str == "_end") Cursor.Done(ls) // End else Cursor.Cont(str :: ls) // Continue }, { (ls, err) => // handle failure err match { case e: RuntimeException => Cursor.Cont(ls) // Skip case _ => Cursor.Fail(err) // Stop with failure } })
MongoDB provides operations to group values from multiple documents, perform operations on the grouped data to return result.
Command distinct
is now provided as collection operation
Example: Find the distinct state from a collection of cities
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson.BSONDocumentimport reactivemongo.api.collections.bson.BSONCollectiondef example14(cities: BSONCollection): Future[Set[String]] = cities.distinct[String, Set]("state")
Example: Aggregates the states with population > 10000000
import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.bson._import reactivemongo.api.Cursorimport reactivemongo.api.collections.bson.BSONCollectiondef example15(cities: BSONCollection): Cursor[BSONDocument] = cities.aggregateWith[BSONDocument]() { framework => import framework.{ Group, Match, SumField } Group(BSONString("$state"))( "totalPop" -> SumField("population")) -> List( Match(document("totalPop" -> document( "$gte" -> 10000000L))) ) }
Standalone library based on Play JSON, usable outside a Play application
Example: Find all documents as JsObject
import scala.concurrent.ExecutionContext.Implicits.globalimport play.api.libs.json._import reactivemongo.api.ReadPreferenceimport reactivemongo.play.json._, collection._def example16(coll: JSONCollection) = coll.find(Json.obj()).cursor[JsObject](ReadPreference.primary).collect[List]()
New helper bulkInsert
Example: Import a JSON resource
import scala.concurrent.ExecutionContext.Implicits.globalimport reactivemongo.play.json.collection._// Import many JSON objects as documents to JSON `collection`def example17(collection: JSONCollection, resource: String) = Helpers.bulkInsert(collection, getClass.getResourceAsStream(resource))
New functions to derive JSON handlers from BSON handlers
Example: jsonOFormat
derives a BSONHandler
import play.api.libs.json.OFormatimport reactivemongo.bson._import reactivemongo.play.json.BSONFormatsdef example18( implicit bsonWriter: BSONDocumentWriter[Person], implicit bsonReader: BSONDocumentReader[Person]): OFormat[Perso] = BSONFormats.jsonOFormat[Person]
New @NamedDatabase
annotation
Example:
# The default URI mongodb.uri = "mongodb://someuser:somepasswd@localhost:27017/foo" # Another one, named with 'bar' mongodb.bar.uri = "mongodb://someuser:somepasswd@localhost:27017/lorem"
Different polls can be injected:
import javax.inject.Injectimport play.modules.reactivemongo._class MyComponent @Inject() ( val defaultApi: ReactiveMongoApi, // for 'mongodb.uri' @NamedDatabase("bar") val barApi: ReactiveMongoApi // for 'mongodb.bar') { /* ... */ }
Bindings for Play routing are available for BSON types
Example: Action foo
import play.api.mvc.{ Action, Controller }import reactivemongo.bson.BSONObjectIDclass Application extends Controller { def foo(id: BSONObjectID) = Action { Ok(s"Foo: ${id.stringify}") }}
BSONObjectID
binding can be used in conf/routes
:
GET /foo/:id Application.foo(id: reactivemongo.bson.BSONObjectID)
New operations to manage a MongoDB instance:
Example: Rename a collection by suffixing
import reactivemongo.api.DefaultDBdef renameWithSuffix( admin: DefaultDB, otherDb: String, collName: String, suffix: String) = admin.renameCollection( otherDb, collName, s"$collName-$suffix")
ReactiveMongo 0.12.4 is compatible with the following runtime:
Next release will be 1.0 (new BSON, Spark module, GeoJSON, certificate authentication, Kamon monitoring ...)
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |