Skip to content

Commit 0a3b827

Browse files
committed
Add query examples and create BSON tutorial page
1 parent 48e60f4 commit 0a3b827

File tree

3 files changed

+265
-44
lines changed

3 files changed

+265
-44
lines changed

docs/tutorial/bson.md

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# BSON Conversion
2+
3+
## Deserialization
4+
5+
By default, the library returns BSON documents and arrays as
6+
MongoDB\Model\BSONDocument and MongoDB\Model\BSONArray objects, respectively.
7+
Both of those classes extend PHP's [ArrayObject][arrayobject] class and
8+
implement the driver's [MongoDB\BSON\Serializable][serializable] and
9+
[MongoDB\BSON\Unserializable][unserializable] interfaces.
10+
11+
[arrayobject]: http://php.net/arrayobject
12+
[serializable]: http://php.net/mongodb-bson-serializable
13+
[unserializable]: http://php.net/mongodb-bson-unserializable
14+
15+
## Type Maps
16+
17+
Most methods that read data from MongoDB support a "typeMap" option, which
18+
allows control over how BSON is converted to PHP. Additionally, the
19+
[MongoDB\Client][client], [MongoDB\Database][database], and
20+
[MongoDB\Collection][collection] classes accept a "typeMap" option, which will
21+
apply to any supporting methods and selected classes by default.
22+
23+
[client]: ../classes/client.md
24+
[database]: ../classes/database.md
25+
[collection]: ../classes/collection.md
26+
27+
The [MongoDB\Client][client], [MongoDB\Database][database], and
28+
[MongoDB\Collection][collection] classes use the following type map by default:
29+
30+
```php
31+
[
32+
'array' => 'MongoDB\Model\BSONArray',
33+
'document' => 'MongoDB\Model\BSONDocument',
34+
'root' => 'MongoDB\Model\BSONDocument',
35+
]
36+
```
37+
38+
## Persistable Classes
39+
40+
Classes implementing [MongoDB\BSON\Persistable][persistable] will be serialized
41+
and deserialized according to the [Persistence][persistence] specification. This
42+
behavior occurs by default in the [driver][ext-mongodb] and does not require use
43+
of the "typeMap" option.
44+
45+
[persistable]: http://php.net/mongodb-bson-persistable
46+
[persistence]: http://php.net/manual/en/mongodb.persistence.php
47+
[ext-mongodb]: https://php.net/mongodb
48+
49+
Given the following class definition:
50+
51+
```
52+
<?php
53+
54+
class Person implements MongoDB\BSON\Persistable
55+
{
56+
private $id;
57+
private $name;
58+
private $createdAt;
59+
60+
public function __construct($name)
61+
{
62+
$this->id = new MongoDB\BSON\ObjectID;
63+
$this->name = (string) $name;
64+
65+
// Get current time in milliseconds since the epoch
66+
$msec = floor(microtime(true) * 1000);
67+
$this->createdAt = new MongoDB\BSON\UTCDateTime($msec);
68+
}
69+
70+
function bsonSerialize()
71+
{
72+
return [
73+
'_id' => $this->id,
74+
'name' => $this->name,
75+
'createdAt' => $this->createdAt,
76+
];
77+
}
78+
79+
function bsonUnserialize(array $data)
80+
{
81+
$this->id = $data['_id'];
82+
$this->name = $data['name'];
83+
$this->createdAt = $data['createdAt'];
84+
}
85+
}
86+
```
87+
88+
The following example constructs a Person object, inserts it into the database,
89+
and reads it back as an object of the same type (without the use of the
90+
"typeMap" option):
91+
92+
```
93+
<?php
94+
95+
$collection = (new MongoDB\Client)->demo->persons;
96+
97+
$result = $collection->insertOne(new Person('Bob'));
98+
99+
$person = $collection->findOne(['_id' => $result->getInsertedId()]);
100+
101+
var_dump($person);
102+
```
103+
104+
The above example would output something similar to:
105+
106+
```
107+
object(Person)#18 (3) {
108+
["id":"Person":private]=>
109+
object(MongoDB\BSON\ObjectID)#15 (1) {
110+
["oid"]=>
111+
string(24) "56fad2c36118fd2e9820cfc1"
112+
}
113+
["name":"Person":private]=>
114+
string(3) "Bob"
115+
["createdAt":"Person":private]=>
116+
object(MongoDB\BSON\UTCDateTime)#17 (1) {
117+
["milliseconds"]=>
118+
int(1459278531218)
119+
}
120+
}
121+
```
122+
123+
The same document in the MongoDB shell might display as:
124+
125+
```
126+
> db.persons.findOne()
127+
{
128+
"_id" : ObjectId("56fad2c36118fd2e9820cfc1"),
129+
"__pclass" : BinData(128,"UGVyc29u"),
130+
"name" : "Bob",
131+
"createdAt" : ISODate("2016-03-29T19:08:51.218Z")
132+
}
133+
```
134+
135+
**Note:** [MongoDB\BSON\Persistable][persistable] may only be used for root and
136+
embedded BSON documents; BSON arrays are not supported.
137+
138+
## Emulating the Legacy Driver
139+
140+
The legacy [mongo extension][ext-mongo] returned both BSON documents and
141+
arrays as PHP arrays. While PHP arrays are convenient to work with, this
142+
behavior was problematic for several reasons:
143+
144+
[ext-mongo]: http://php.net/mongo
145+
146+
* Different BSON types could deserialize to the same PHP value (e.g.
147+
`{"0": "foo"}` and `["foo"]`), which made it impossible to infer the
148+
original BSON type.
149+
150+
* Numerically indexed PHP arrays would be serialized as BSON documents if there
151+
was a gap in their key sequence. Such gaps were easily (and inadvertently)
152+
caused by unsetting a key to remove an element and forgetting to reindex the
153+
array.
154+
155+
The libary's MongoDB\Model\BSONDocument and MongoDB\Model\BSONArray classes
156+
address these concerns by preserving the BSON type information during
157+
serialization and deserialization; however, some users may still prefer the
158+
legacy behavior. If desired, the following "typeMap" option can be used to have
159+
the library return everything as a PHP array:
160+
161+
```
162+
<?php
163+
164+
$client = new MongoDB\Client(
165+
null,
166+
[],
167+
['typeMap' => ['root' => 'array', 'document' => 'array', 'array' => 'array']]
168+
);
169+
170+
$document = $client->demo->zips->findOne(
171+
['_id' => '94301'],
172+
['typeMap' => ['root' => 'array', 'document' => 'array', 'array' => 'array']]
173+
);
174+
175+
var_dump($document);
176+
```
177+
178+
The above example would output something similar to:
179+
180+
```
181+
array(5) {
182+
["_id"]=>
183+
string(5) "94301"
184+
["city"]=>
185+
string(9) "PALO ALTO"
186+
["loc"]=>
187+
array(2) {
188+
[0]=>
189+
float(-122.149685)
190+
[1]=>
191+
float(37.444324)
192+
}
193+
["pop"]=>
194+
int(15965)
195+
["state"]=>
196+
string(2) "CA"
197+
}
198+
```

docs/tutorial/crud.md

+66-44
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,12 @@ the [MongoDB Manual][crud].
1111
[crud-spec]: https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst
1212
[crud]: https://docs.mongodb.org/manual/crud/
1313

14-
## Querying
15-
16-
### Finding One Document
14+
## Finding One Document
1715

1816
The [findOne()][findone] method returns the first matched document, or null if
19-
no document was matched. By default, the library returns BSON documents and
20-
arrays as MongoDB\Model\BSONDocument and MongoDB\Model\BSONArray objects,
21-
respectively. Both of those classes extend PHP's [ArrayObject][arrayobject]
22-
class and implement the driver's [MongoDB\BSON\Serializable][serializable] and
23-
[MongoDB\BSON\Unserializable][unserializable] interfaces.
17+
no document was matched.
2418

2519
[findone]: ../classes/collection.md#findone
26-
[arrayobject]: http://php.net/arrayobject
27-
[serializable]: http://php.net/mongodb-bson-serializable
28-
[unserializable]: http://php.net/mongodb-bson-unserializable
2920

3021
```
3122
<?php
@@ -65,21 +56,55 @@ object(MongoDB\Model\BSONDocument)#13 (1) {
6556
}
6657
```
6758

68-
Most methods that read data from MongoDB support a "typeMap" option, which
69-
allows control over how BSON is converted to PHP. If desired, this option can be
70-
used to return everything as a PHP array, as was done in the legacy
71-
[mongo extension][ext-mongo]:
59+
## Finding Many Documents
60+
61+
The [find()][find] method returns a [MongoDB\Driver\Cursor][cursor] object,
62+
which may be iterated upon to access all matched documents. The following
63+
example queries for all zip codes in a given city:
64+
65+
[find]: ../classes/collection.md#find
66+
[cursor]: http://php.net/mongodb-driver-cursor
67+
68+
```
69+
<?php
70+
71+
$collection = (new MongoDB\Client)->demo->zips;
72+
73+
$cursor = $collection->find(['city' => 'JERSEY CITY', 'state' => 'NJ']);
74+
75+
foreach ($cursor as $document) {
76+
echo $document['_id'], "\n";
77+
}
78+
```
79+
80+
The above example would output something similar to:
81+
82+
```
83+
07302
84+
07304
85+
07305
86+
07306
87+
07307
88+
07310
89+
```
90+
91+
## Query Projection
92+
93+
Queries may include a [projection][projection] to include or exclude specific
94+
fields in the returned documents. The following example selects only the
95+
population field for the zip code:
96+
97+
[projection]: https://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/
7298

73-
[ext-mongo]: http://php.net/mongo
7499

75100
```
76101
<?php
77102
78103
$collection = (new MongoDB\Client)->demo->zips;
79104
80105
$document = $collection->findOne(
81-
['_id' => '94301'],
82-
['typeMap' => ['root' => 'array', 'document' => 'array', 'array' => 'array']]
106+
['_id' => '10011'],
107+
['projection' => ['pop => 1']]
83108
);
84109
85110
var_dump($document);
@@ -88,39 +113,37 @@ var_dump($document);
88113
The above example would output something similar to:
89114

90115
```
91-
array(5) {
92-
["_id"]=>
93-
string(5) "94301"
94-
["city"]=>
95-
string(9) "PALO ALTO"
96-
["loc"]=>
116+
object(MongoDB\Model\BSONDocument)#12 (1) {
117+
["storage":"ArrayObject":private]=>
97118
array(2) {
98-
[0]=>
99-
float(-122.149685)
100-
[1]=>
101-
float(37.444324)
119+
["_id"]=>
120+
string(5) "10011"
121+
["pop"]=>
122+
int(46560)
102123
}
103-
["pop"]=>
104-
int(15965)
105-
["state"]=>
106-
string(2) "CA"
107124
}
108125
```
109126

110-
### Finding Many Documents
127+
**Note:** the "_id" field is included by default unless explicitly excluded.
111128

112-
The [find()][find] method returns a [MongoDB\Driver\Cursor][cursor] object,
113-
which may be iterated upon to access all matched documents.
129+
## Limit, Sort, and Skip Options
114130

115-
[find]: ../classes/collection.md#find
116-
[cursor]: http://php.net/mongodb-driver-cursor
131+
In addition to criteria, queries may take options to limit, sort, and skip
132+
returned documents. The following example queries for the five most populous
133+
zip codes in the United States:
117134

118135
```
119136
<?php
120137
121138
$collection = (new MongoDB\Client)->demo->zips;
122139
123-
$cursor = $collection->find(['city' => 'JERSEY CITY', 'state' => 'NJ']);
140+
$cursor = $collection->find(
141+
[],
142+
[
143+
'limit' => 5,
144+
'sort' => ['pop' => -1],
145+
]
146+
);
124147
125148
foreach ($cursor as $document) {
126149
echo $document['_id'], "\n";
@@ -130,10 +153,9 @@ foreach ($cursor as $document) {
130153
The above example would output something similar to:
131154

132155
```
133-
07302
134-
07304
135-
07305
136-
07306
137-
07307
138-
07310
156+
60623: CHICAGO, IL
157+
11226: BROOKLYN, NY
158+
10021: NEW YORK, NY
159+
10025: NEW YORK, NY
160+
90201: BELL GARDENS, CA
139161
```

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pages:
99
- 'Getting Started': 'getting-started.md'
1010
- 'Upgrade Guide': 'upgrade-guide.md'
1111
- Tutorial:
12+
- 'BSON Conversion': 'tutorial/bson.md'
1213
- 'CRUD Operations': 'tutorial/crud.md'
1314
- 'Database Commands': 'tutorial/commands.md'
1415
- 'Indexes': 'tutorial/indexes.md'

0 commit comments

Comments
 (0)