====
BSON
====
.. default-domain:: mongodb
.. contents:: On this page
:local:
:backlinks: none
:depth: 1
:class: singlecol
Overview
--------
MongoDB stores data records as BSON documents. BSON is a binary
representation of :term:`JSON` documents, though it contains more data
types than JSON. For the BSON spec, see `bsonspec.org `_.
By default, the |php-library| returns BSON documents as
``MongoDB\Model\BSONDocument`` objects and BSON arrays as
``MongoDB\Model\BSONArray`` objects. ``MongoDB\Model\BSONDocument`` and
``MongoDB\Model\BSONArray`` extend PHP's
:php:`ArrayObject ` class and implement the MongoDB PHP
driver's :php:`MongoDB\\BSON\\Serializable `
and :php:`MongoDB\\BSON\\Unserializable `
interfaces.
Type Maps
---------
Most methods that read data from MongoDB support a ``typeMap`` option,
which allows control over how BSON is converted to PHP. Additionally,
the :phpclass:`MongoDB\\Client`, :phpclass:`MongoDB\\Database`, and
:phpclass:`MongoDB\\Collection` classes accept a ``typeMap`` option,
which applies to any supporting methods and selected classes by default.
The :phpclass:`MongoDB\\Client`, :phpclass:`MongoDB\\Database`, and
:phpclass:`MongoDB\\Collection` classes use the following type map by
default:
.. code-block:: php
[
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
]
Serialization and deserialization of PHP variables into MongoDB
---------------------------------------------------------------
``Persistable`` Classes
~~~~~~~~~~~~~~~~~~~~~~~
The PHP driver's :php:`persistence ` specification
specifies how classes implementing :php:`MongoDB\\BSON\\Persistable
` are serialized and deserialized, and is
analogous to PHP's :php:`Serializable interface `.
The PHP :php:`driver ` automatically handles serialization and
deserialization for classes implementing ``MongoDB\BSON\Persistable``
without requiring the use of the ``typeMap`` option.
Consider the following class definition:
.. code-block:: php
id = new MongoDB\BSON\ObjectID;
$this->name = (string) $name;
// Get current time in milliseconds since the epoch
$msec = floor(microtime(true) * 1000);
$this->createdAt = new MongoDB\BSON\UTCDateTime($msec);
}
function bsonSerialize()
{
return [
'_id' => $this->id,
'name' => $this->name,
'createdAt' => $this->createdAt,
];
}
function bsonUnserialize(array $data)
{
$this->id = $data['_id'];
$this->name = $data['name'];
$this->createdAt = $data['createdAt'];
}
}
The following constructs a ``Person`` object, inserts it into the
database, and reads it back as an object of the same type:
.. code-block:: php
demo->persons;
$result = $collection->insertOne(new Person('Bob'));
$person = $collection->findOne(['_id' => $result->getInsertedId()]);
var_dump($person);
The output would then resemble:
.. code-block:: none
object(Person)#18 (3) {
["id":"Person":private]=>
object(MongoDB\BSON\ObjectID)#15 (1) {
["oid"]=>
string(24) "56fad2c36118fd2e9820cfc1"
}
["name":"Person":private]=>
string(3) "Bob"
["createdAt":"Person":private]=>
object(MongoDB\BSON\UTCDateTime)#17 (1) {
["milliseconds"]=>
int(1459278531218)
}
}
The same document in the MongoDB shell might display as:
.. code-block:: js
{
"_id" : ObjectId("56fad2c36118fd2e9820cfc1"),
"__pclass" : BinData(128,"UGVyc29u"),
"name" : "Bob",
"createdAt" : ISODate("2016-03-29T19:08:51.218Z")
}
.. note::
:php:`MongoDB\\BSON\\Persistable ` may only be used
for root and embedded BSON documents. BSON arrays are not supported.
Emulating the Legacy Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The legacy :php:`mongo extension ` returned both BSON
documents and arrays as PHP arrays. While PHP arrays are convenient to
work with, this behavior was problematic:
- Different BSON types could deserialize to the same PHP value (e.g.
``{"0": "foo"}`` and ``["foo"]``), which made it impossible to infer
the original BSON type.
- Numerically-indexed PHP arrays would be serialized as BSON documents
if there was a gap in their key sequence. Such gaps were easily
caused by unsetting a key to remove an element and
forgetting to reindex the array.
The |php-library|'s ``MongoDB\Model\BSONDocument`` and ``MongoDB\Model\BSONArray``
classes address these
concerns by preserving the BSON type information during serialization
and deserialization; however, some users may still prefer the legacy
behavior. If desired, you can use the ``typeMap`` option to have
the library return everything as a PHP array:
.. code-block:: php
[
'root' => 'array', 'document' => 'array', 'array' => 'array'
],
]
);
$document = $client->demo->zips->findOne(
['_id' => '94301'],
['typeMap' => [
'root' => 'array', 'document' => 'array', 'array' => 'array'
],
]
);
var_dump($document);
The above example would output something similar to:
.. code-block:: php
array(5) {
["_id"]=>
string(5) "94301"
["city"]=>
string(9) "PALO ALTO"
["loc"]=>
array(2) {
[0]=>
float(-122.149685)
[1]=>
float(37.444324)
}
["pop"]=>
int(15965)
["state"]=>
string(2) "CA"
}