Skip to content

Commit e189033

Browse files
committed
DOCSP-43464: operations with builders
1 parent 5250d43 commit e189033

File tree

6 files changed

+406
-3
lines changed

6 files changed

+406
-3
lines changed

source/aggregation.txt

+6
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ The examples in this section are adapted from the {+mdb-server+} manual.
228228
Each example provides a link to the sample data that you can insert into
229229
your database to test the aggregation operation.
230230

231+
.. tip:: Operations with Builders
232+
233+
You can use builders to support non-aggregation operations such as
234+
find and update operations. To learn more, see the :ref:`php-builders`
235+
guide.
236+
231237
Filter and Group Example
232238
~~~~~~~~~~~~~~~~~~~~~~~~
233239

source/builders.txt

+304
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
.. _php-builders:
2+
3+
========================
4+
Operations with Builders
5+
========================
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: aggregation, query, code example, type-safe
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn about the **builder classes**
24+
that the {+library-short+} provides to create types used in your
25+
operations. You can use the builder classes and factory methods from the
26+
:ref:`php-aggregation-builder-api` feature to create filters for other
27+
operations such as find, update, and delete operations.
28+
29+
Using builders to create queries helps you identify errors at compile
30+
time and avoid them at runtime. This guide provides information on
31+
builder classes that you can use for the following tasks:
32+
33+
- :ref:`Creating a filter definition <php-builders-filter>`
34+
- :ref:`Defining an update operation <php-builders-update>`
35+
- :ref:`Filtering a change stream <php-builders-changestream>`
36+
37+
.. note:: Options
38+
39+
You cannot specify options by using factory methods for the equivalent
40+
aggregation stages. For example, you cannot use the ``Stage::limit()`` method
41+
to set a returned documents limit on your find operation. You must specify
42+
options by using the string-based syntax, as shown in the following code:
43+
44+
.. code-block:: php
45+
46+
$options = [
47+
'limit' => 5,
48+
'<option name>' => '<specification>',
49+
];
50+
51+
This guide provides examples of how to use builders in non-aggregation
52+
operations. To view aggregation examples, see the :ref:`php-aggregation`
53+
guide.
54+
55+
Sample Data
56+
~~~~~~~~~~~
57+
58+
The examples in this guide use the ``shipwrecks`` collection in the
59+
``sample_geospatial`` database from the :atlas:`Atlas sample datasets
60+
</sample-data>`. To access this collection from your PHP application,
61+
instantiate a ``MongoDB\Client`` that connects to an Atlas cluster
62+
and assign the following value to your ``$collection`` variable:
63+
64+
.. literalinclude:: /includes/builders.php
65+
:language: php
66+
:dedent:
67+
:start-after: start-db-coll
68+
:end-before: end-db-coll
69+
70+
To learn how to create a free MongoDB Atlas cluster and load the sample
71+
datasets, see the :atlas:`Get Started with Atlas </getting-started>` guide.
72+
73+
Import Builder Classes
74+
----------------------
75+
76+
To run the examples in this guide, you must import the following classes
77+
into your application:
78+
79+
.. literalinclude:: /includes/builders.php
80+
:language: php
81+
:dedent:
82+
:start-after: start-imports
83+
:end-before: end-imports
84+
85+
.. _php-builders-filter:
86+
87+
Create a Filter
88+
---------------
89+
90+
You can use factory methods from the ``Query`` builder class to create
91+
filter definitions to use in find, update, and delete operations. To
92+
learn more about creating filters, see the :ref:`php-specify-query` guide.
93+
94+
The following steps describe how to create a filter definition by using
95+
builders:
96+
97+
1. Instantiate the ``QueryInterface`` by calling the ``Query::query()``
98+
method.
99+
100+
#. Pass the field name to compare and a factory method from the
101+
``Query`` class. You can pass one or more pairs of field names and
102+
criteria to the ``QueryInterface``.
103+
104+
The following code shows the template to create a filter definition by
105+
using builders:
106+
107+
.. code-block:: php
108+
109+
$filter = Query::query(
110+
<field name>: Query::<factory method>(<parameters>),
111+
<field name>: Query::<factory method>(<parameters>),
112+
...
113+
);
114+
115+
The following sections provide examples that use builders to create
116+
filter definitions for different operations.
117+
118+
Retrieve Example
119+
~~~~~~~~~~~~~~~~
120+
121+
This example performs the following actions:
122+
123+
- Uses the ``Query::eq()`` factory method to match documents in which
124+
the ``feature_type`` field value is ``'Wrecks - Visible'``
125+
- Uses the ``Query::near()`` factory method to match documents in which
126+
the ``feature_type`` field value is ``'Wrecks - Visible'``
127+
- Calls the :phpmethod:`MongoDB\Collection::find()`
128+
method to retrieve the matching documents
129+
- Prints the matching documents
130+
131+
.. io-code-block::
132+
:copyable:
133+
134+
.. input:: /includes/builders.php
135+
:start-after: start-find
136+
:end-before: end-find
137+
:language: php
138+
:dedent:
139+
140+
.. output::
141+
:language: json
142+
:visible: false
143+
144+
{"_id":...,"feature_type":"Wrecks - Visible","coordinates":[-79.9137115,9.3390503],...}
145+
{"_id":...,"feature_type":"Wrecks - Visible","coordinates":[-79.9357223,9.3340302],...}
146+
{"_id":...,"feature_type":"Wrecks - Visible","coordinates":[-79.9081268,9.3547792],...}
147+
// Results truncated
148+
149+
To learn more about find operations, see the :ref:`php-retrieve` guide.
150+
151+
Delete Example
152+
~~~~~~~~~~~~~~
153+
154+
This example performs the following actions:
155+
156+
- Uses the ``Query::regex()`` factory method to match documents in which
157+
the ``feature_type`` field value contains the string ``'nondangerous'``
158+
- Calls the :phpmethod:`MongoDB\Collection::deleteOne()`
159+
method to delete the first matching document
160+
- Prints the number of deleted documents
161+
162+
.. io-code-block::
163+
:copyable:
164+
165+
.. input:: /includes/builders.php
166+
:start-after: start-deleteone
167+
:end-before: end-deleteone
168+
:language: php
169+
:dedent:
170+
171+
.. output::
172+
:language: none
173+
:visible: false
174+
175+
Deleted documents: 1
176+
177+
To learn more about delete operations, see the :ref:`php-write-delete`
178+
guide.
179+
180+
.. _php-builders-update:
181+
182+
Define an Update Document
183+
-------------------------
184+
185+
You can use factory methods from the ``Stage`` builder class to update
186+
or create field values in your update operations. To learn more about
187+
updating documents, see the :ref:`php-write-update` guide.
188+
189+
.. important::
190+
191+
The only update operation that you can express by using builders uses
192+
the ``$set`` operator. This operator allows you to replace the value of
193+
a field with a specified value or create a new field that has a specified
194+
value. To learn more, see the :manual:`$set </reference/operator/update/set/>`
195+
reference in the {+mdb-server+} manual.
196+
197+
The following steps describe how to create an update document by using
198+
builders:
199+
200+
1. Create a ``Pipeline`` instance.
201+
202+
#. Pass one or more ``$set`` stages by calling the ``Stage::set()``
203+
method and passing a field name and a value.
204+
205+
The following code shows the template to define an update by using
206+
builders:
207+
208+
.. code-block:: php
209+
210+
$update = new Pipeline(
211+
Stage::set(<field name>: <value>),
212+
Stage::set(<field name>: <value>),
213+
...
214+
);
215+
216+
This example performs the following actions:
217+
218+
- Uses the ``Query::eq()`` factory method to match documents in which
219+
the ``watlev`` field value is ``'partly submerged at high water'``
220+
- Uses builders to specify an update that sets
221+
sets the ``year`` field to ``1870``
222+
- Calls the :phpmethod:`MongoDB\Collection::updateOne()`
223+
method to perform the update
224+
- Prints the number of updated documents
225+
226+
.. io-code-block::
227+
:copyable:
228+
229+
.. input:: /includes/builders.php
230+
:start-after: start-updateone
231+
:end-before: end-updateone
232+
:language: php
233+
:dedent:
234+
235+
.. output::
236+
:language: none
237+
:visible: false
238+
239+
Updated documents: 1
240+
241+
.. _php-builders-changestream:
242+
243+
Modify Change Stream Output
244+
---------------------------
245+
246+
You can use factory methods from the ``Stage`` class to modify a change
247+
stream's output by creating a pipeline. To learn more about change
248+
streams, see the :ref:`php-change-streams` guide.
249+
250+
The following steps describe how to create a change stream filter by
251+
using builders:
252+
253+
1. Create an array.
254+
255+
#. Pass one or more ``$match`` stages by calling factory methods from
256+
the ``Stage`` class and the required parameters.
257+
258+
The following code shows the template to modify change stream output by
259+
using builders:
260+
261+
.. code-block:: php
262+
263+
$pipeline = new Pipeline(
264+
Stage::<factory method>(...),
265+
Stage::<factory method>(...),
266+
...
267+
);
268+
269+
You can pass this pipeline to the following methods:
270+
271+
- :phpmethod:`MongoDB\Client::watch()`
272+
- :phpmethod:`MongoDB\Database::watch()`
273+
- :phpmethod:`MongoDB\Collection::watch()`
274+
275+
This example performs the following actions:
276+
277+
- Uses the ``Stage::match()`` method to filter for only update change
278+
events
279+
- Uses the ``Stage::project()`` method to output only the specified change
280+
event fields
281+
- Calls the :phpmethod:`MongoDB\Collection::watch()`
282+
method to open the change stream with the option to output the full
283+
document after update
284+
- Prints change events as they occur
285+
286+
.. io-code-block::
287+
:copyable:
288+
289+
.. input:: /includes/builders.php
290+
:start-after: start-cs
291+
:end-before: end-cs
292+
:language: php
293+
:dedent:
294+
295+
.. output::
296+
:language: json
297+
:visible: false
298+
299+
{
300+
"_id":...,
301+
"operationType":"update",
302+
"fullDocument":{"_id":...,"feature_type":"Wrecks - Visible",...},
303+
"ns":{"db":"sample_geospatial","coll":"shipwrecks"}
304+
}

source/includes/builders.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
// start-imports
4+
use MongoDB\Builder\Pipeline;
5+
use MongoDB\Builder\Query;
6+
use MongoDB\Builder\Stage;
7+
// end-imports
8+
9+
require 'vendor/autoload.php';
10+
11+
$uri = getenv('MONGODB_URI') ?: throw new RuntimeException('Set the MONGODB_URI variable to your Atlas URI that connects to the sample dataset');
12+
$client = new MongoDB\Client($uri);
13+
14+
// start-db-coll
15+
$collection = $client->sample_geospatial->shipwrecks;
16+
// end-db-coll
17+
18+
// start-find
19+
$docs = $collection->find(Query::query(
20+
feature_type: Query::eq('Wrecks - Visible'),
21+
coordinates: Query::near(
22+
Query::geometry(
23+
type: 'Point',
24+
coordinates: [-79.9, 9.3],
25+
),
26+
maxDistance: 10000,
27+
)
28+
));
29+
30+
foreach ($docs as $doc) {
31+
echo json_encode($doc), PHP_EOL;
32+
}
33+
// end-find
34+
35+
// start-deleteone
36+
$result = $collection->deleteOne(Query::query(
37+
feature_type: Query::regex('nondangerous$', '')
38+
));
39+
40+
echo 'Deleted documents: ', $result->getDeletedCount(), PHP_EOL;
41+
// end-deleteone
42+
43+
// start-updateone
44+
$result = $collection->updateOne(
45+
Query::query(watlev: Query::eq('partly submerged at high water')),
46+
new Pipeline(
47+
Stage::set(year: 1870),
48+
),
49+
);
50+
51+
echo 'Updated documents: ', $result->getModifiedCount(), PHP_EOL;
52+
// end-updateone
53+
54+
// start-cs
55+
$pipeline = [
56+
Stage::match(operationType: Query::eq('update')),
57+
Stage::project(operationType: 1, ns: 1, fullDocument: 1),
58+
];
59+
60+
$changeStream = $collection->watch(
61+
$pipeline,
62+
['fullDocument' => MongoDB\Operation\Watch::FULL_DOCUMENT_UPDATE_LOOKUP]
63+
);
64+
65+
for ($changeStream->rewind(); true; $changeStream->next()) {
66+
if (! $changeStream->valid()) {
67+
continue;
68+
}
69+
$event = $changeStream->current();
70+
echo json_encode($event), PHP_EOL;
71+
72+
if ($event['operationType'] === 'invalidate') {
73+
break;
74+
}
75+
}
76+
// end-cs

0 commit comments

Comments
 (0)