Documents
Overview
The Scala driver includes two Scala-specific representations for BSON
documents. Following the convention from the Scala collections library,
there are immutable and mutable implementations of the Document
type. The
underlying implementations of Document
use the type-safe
BsonDocument class. The BSON classes are available from the
org.mongodb.scala.bson
namespace, which includes type aliases and
companion objects. These objects should suffice for many use cases, but
for advanced use cases you may need to use classes from the org.bson
namespace directly.
Important
Duplicate Key Names
The server’s behavior regarding duplicate key names in a document is undefined. When a document with duplicate key names is decoded, the driver will assign the last value associated with the duplicate key. Storing such a document will cause the other values to be lost.
Note
The Scala Document
classes implement TraversableLike[(String,
BsonValue)]
and the general API mirrors that of a Map[String,
BsonValue]
value. However, unlike Map
, implementations of TraversableLike
enable strict type safety as there is no variance in the value type.
BsonValue
is the type-safe representation of a BSON type from the
org.bson
library and represents specific value types. The most commonly
used value types are as follows:
BSON Type | Scala Type |
---|---|
Document | org.mongodb.scala.bson.Document |
Array | List |
Date | Date or int (milliseconds since epoch) |
Boolean | Boolean |
Double | Double |
Int32 | Integer |
Int64 | Long |
String | String |
Binary | Array[Byte] |
ObjectId | ObjectId |
Null | None |
It is possible to change or extend these mappings, a process described in the following sections.
The following sections describe the two main Document
classes.
Immutable Documents
Similar to the Scala collections library, the immutable class is the preferred
class. For convenience, it is aliased to org.mongodb.scala.Document
and
org.mongodb.scala.bson.Document
as well as being available from
org.mongodb.scala.bson.collection.immutable.Document
.
Instances of this type are guaranteed to be immutable for everyone. Such a collection will never change after it is created. Therefore, you can rely on the fact that accessing the same collection value repeatedly at different points in time will always yield a collection with the same elements.
import org.mongodb.scala.bson._ val doc1 = Document("AL" -> BsonString("Alabama")) val doc2 = doc1 + ("AK" -> BsonString("Alaska")) val doc3 = doc2 ++ Document("AR" -> BsonString("Arkansas"), "AZ" -> BsonString("Arizona"))
Mutable Documents
To get the mutable Document
type, you need to import it explicitly
from org.mongodb.scala.collections.mutable.Document
. The mutable
Document
can be updated or extended in place. This means you can change,
add, or remove elements of the Document
as a side effect. Similar to Scala
collections, when dealing with mutable types you need to understand
which code changes which collection and when.
import org.mongodb.scala.bson._ import org.mongodb.scala.bson.collection.mutable.Document val doc = Document("AL" -> BsonString("Alabama")) val doc1 = doc + ("AK" -> BsonString("Alaska")) // doc not mutated but new doc created doc1 ++= Document("AR" -> BsonString("Arkansas"), "AZ" -> BsonString("Arizona")) // doc1 mutated as ++= changes in place.
Implicit Conversions
For many of the BsonValue
types, there are obvious direct mappings from a
Scala type. For example, a String
maps to BsonString
, an Int
maps to
BsonInt32
and a Long
maps to a BsonInt64
. For convenience, these types
can be used directly with Document
types and they are converted by the
contract traits in the BsonMagnets
object. As long as there is an
implicit BsonTransformer
in scope for any given type, then that type can
be converted into a BsonValue
.
The following BsonTransformers
are in scope by default:
Scala Type | BsonValue |
---|---|
Boolean | BsonBoolean |
String | BsonString |
Array[Byte] | BsonBinary |
Regex | BsonRegex |
Date | BsonDateTime |
ObjectId | BsonObjectId |
Int | BsonInt32 |
Long | BsonInt64 |
Double | BsonDouble |
immutable.Document | BsonDocument |
mutable.Document | BsonDocument |
Option[T] | BsonValue where T has a BsonTransformer |
Seq[(String, T)] | BsonDocument where T has a BsonTransformer |
Seq[T] | BsonArray where T has a BsonTransformer |
BsonValue | BsonValue |
import org.mongodb.scala.Document val doc1 = Document("AL" -> "Alabama") val doc2 = doc1 + ("AK" -> "Alaska") val doc3 = doc2 ++ Document("AR" -> "Arkansas", "population" -> 2.966)
This is achieved by making use of the Magnet Pattern, which you can learn more about in the Magnet Pattern blog post on spray.io.
In the API where we would normally expect a single value or a key-value
pair or many key value pairs, such as BsonValue
, (String
, BsonValue
) or
Iterable[(String, BsonValue)]
, we require anything that can become those
types via CanBeX
traits that handle the implicit conversions necessary
to conform to the correct types. These traits are CanBeBsonValue
,
CanBeBsonElement
and CanBeBsonElements
.
One such example is adding a key-value pair to a Document
or a list of
values:
val doc1 = Document("AL" -> "Alabama") val doc2 = Document("codes" -> List("AL", "AK", "AR"))
Bson
The driver also contains a small but powerful interface called Bson
. Any
class that represents a BSON document, whether included in the driver
itself or from a third party, can implement this interface and can then
be used any place in the high-level API where a BSON document is
required. For example:
collection.find(Document("x" -> 1)) collection.find(Filters.eq("x", 1))