Reactive Scala Driver for MongoDB
Asynchronous & Non-Blocking
Overview of the ReactiveMongo BSON library
The Biːsən library of ReactiveMongo implements the BSON format, or Binary JSON, which is used by MongoDB to encode data.
The library is designed with the following points in mind:
- Ease of use
- Strong typing
- Efficiency
It can be configured in a build.sbt
as below.
libraryDependencies += "org.reactivemongo" %% "reactivemongo-bson-api" % "1.1.0-RC14"
See Scaladoc
Documents and values
There is one Scala class for each BSON type, all in the reactivemongo.api.bson
package.
import scala.util.Try
import reactivemongo.api.bson._
val bsonDouble = BSONDouble(12.34D)
val bsonStr = BSONString("foo")
val bsonInt = BSONInteger(2345)
// BSON array: [ 12.34, "foo", 2345 ]
val bsonArray = BSONArray(bsonDouble, bsonStr, bsonInt)
val bsonEmptyDoc: BSONDocument = BSONDocument.empty
/* BSON Document:
{
'foo': 'bar',
'lorem': 2,
'values': [ 12.34, "foo", 2345 ],
'nested': {
'position': 1000,
'score': 1.2
}
}
*/
val bsonDoc = BSONDocument(
"foo" -> "bar", // as BSONString
"lorem" -> 2, // as BSONInteger
"values" -> bsonArray,
"nested" -> BSONDocument(
"position" -> 1000,
"score" -> 1.2D // as BSONDouble
)
)
val bsonBin = BSONBinary(Array[Byte](0, 1, 2), Subtype.GenericBinarySubtype)
// See Subtype
val bsonObjectID = BSONObjectID.generate()
val bsonBool = BSONBoolean(true)
val bsonDateTime = BSONDateTime(System.currentTimeMillis())
val bsonRegex = BSONRegex("/foo/bar/", "g")
val bsonJavaScript = BSONJavaScript("lorem(0)")
val bsonJavaScriptWs = BSONJavaScriptWS("bar", BSONDocument("bar" -> 1))
val bsonTimestamp = BSONTimestamp(45678L)
val bsonLong = BSONLong(Long.MaxValue)
val bsonZeroDecimal = BSONDecimal.PositiveZero
val bsonDecimal: Try[BSONDecimal] =
BSONDecimal.fromBigDecimal(BigDecimal("12.23"))
val bsonNull = BSONNull
val bsonMinKey = BSONMinKey
val bsonMaxKey = BSONMaxKey
Documents
A document is represented by BSONDocument
, which is basically an immutable list of key-value pairs. Since it is the most used BSON type, one of the main focuses of the ReactiveMongo BSON library is to make manipulations of BSONDocument as easy as possible.
import reactivemongo.api.bson._
/* Document: {
'title': 'Everybody Knows this is Nowhere',
'releaseYear': 1969
} */
val album = BSONDocument(
"title" -> "Everybody Knows this is Nowhere",
"releaseYear" -> 1969)
val albumTitle = album.getAsOpt[String]("title")
albumTitle match {
case Some(title) =>
println(s"The title of this album is $title")
case _ =>
println("""This document does not contain a title
(or title is not a BSONString)""")
}
The API for BSONDocument
provides the function getAsOpt
and getAsTry
to get the field values, and getOrElse
.
import scala.util.Try
import reactivemongo.api.bson._
def bar(doc: BSONDocument): Unit = {
val i: Option[Int] = doc.getAsOpt[Int]("fieldNameInt")
val d: Option[Double] = doc.getAsOpt[Double]("fieldNameDouble")
val l: Try[Long] = doc.getAsTry[Long]("fieldNameLong")
val s: Try[String] = doc.getAsTry[String]("fieldNameStr")
val fallback: String = doc.getOrElse[String]("strField", "defaultValue")
// Equivalent to: doc.getAsOpt[String]("strField").getOrElse("defaultValue")
}
Field utilities are provided for the most common types:
import reactivemongo.api.bson._
def foo(doc: BSONDocument): Unit = {
val i: Option[Int] = doc.int("fieldNameInt")
val d: Option[Double] = doc.double("fieldNameDouble")
val l: Option[Long] = doc.long("fieldNameLong")
val s: Option[String] = doc.string("fieldNameStr")
val a: Option[Seq[BSONValue]] = doc.array("fieldNameArr")
val b: Option[Boolean] = doc.booleanLike("fieldNameBool")
val c: Option[BSONDocument] = doc.child("nestedDoc")
val _: List[BSONDocument] = doc.children("arrayOfDocs")
}
Numeric & Boolean values
The traits BSONNumberLike
and BSONBooleanLike
are also kept in the new API, to generalize the handling of numerical and boolean values.
import scala.util.Try
import reactivemongo.api.bson._
val doc = BSONDocument("ok" -> 1.0D /* BSON double */ )
val bsonNumLike: Try[BSONNumberLike] = doc.getAsTry[BSONNumberLike]("ok")
val intLike: Try[Int] = bsonNumLike.flatMap(_.toInt) // =Success(1)
val bsonBoolLike: Try[BSONBooleanLike] = doc.getAsTry[BSONBooleanLike]("ok")
val boolLike: Try[Boolean] = bsonBoolLike.flatMap(_.toBoolean) // =Success(true)
Now Float
is handled as a BSON double (as Double
, as it’s now possible to have several Scala types corresponding to the same BSON type).
The Decimal128 type introduced by MongoDB 3.4 is also supported, as BSONDecimal
, and can be read or write as java.math.BigDecimal
.
import scala.util.Try
import reactivemongo.api.bson._
def readFloat(
doc: BSONDocument,
n: String
)(implicit r: BSONReader[Float]): Try[Float] = doc.getAsTry[Float](n)
Still to make the API simpler, the BSON singleton types (e.g. BSONNull
) are also defined with a trait, to be able to reference them without .type
suffix.
import reactivemongo.api.bson.BSONNull
def useNullBefore(bson: BSONNull.type) = println(".type was required")
def useNullNow(bson: BSONNull) = print("Suffix no longer required")
Binary values
The BSONBinary
extractor now only bind subtype:
import reactivemongo.api.bson.{ BSONBinary, Subtype }
def binExtractor = {
BSONBinary(Array[Byte](0, 1, 2), Subtype.GenericBinarySubtype) match {
case genBin @ BSONBinary(Subtype.GenericBinarySubtype) =>
genBin.byteArray
case _ => ???
}
}
Miscellaneous
- Type
BSONArray
is no longer anElementProducer
(only a value producer). - The function
BSONObjectID.valueAsArray
is renamed tobyteArray
. - The deprecated type
BSONDBPointer
is removed. - The scope property is now supported by
BSONJavascriptWS
Summary
BSON | Description | JVM type |
---|---|---|
BSONBinary | binary data | Array[Byte] |
BSONBoolean | boolean | Boolean |
BSONDateTime | UTC Date Time | java.util.Date |
BSONDecimal | Decimal128 | java.math.BigDecimal |
BSONDouble | 64-bit IEEE 754 floating point | Double |
BSONInteger | 32-bit integer | Int |
BSONJavaScript | JavaScript code | None |
BSONJavaScriptWS | JavaScript scoped code | None |
BSONLong | 64-bit integer | Long |
BSONMaxKey | max key | None |
BSONMinKey | min key | None |
BSONNull | null | None |
BSONObjectID | 12 bytes default id type in MongoDB | None |
BSONRegex | regular expression | None |
BSONString | UTF-8 string | String |
BSONSymbol | deprecated in the protocol | None |
BSONTimestamp | special date type used in MongoDB internals | None |
BSONUndefined | deprecated in the protocol | None |
All these classes extend BSONValue.