Skip to content

Commit 99d6179

Browse files
committed
DOCSP-43919: aggregation builder
1 parent 3daba83 commit 99d6179

File tree

4 files changed

+305
-31
lines changed

4 files changed

+305
-31
lines changed

snooty.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ php-library = "MongoDB PHP Library"
4141
[constants]
4242
php-library = "MongoDB PHP Library"
4343
version = "1.20"
44+
source-gh-branch = "v1.x"
4445
full-version = "{+version+}.0"
4546
extension-short = "PHP extension"
4647
mdb-server = "MongoDB Server"

source/aggregation.txt

Lines changed: 206 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ The **aggregation pipeline** is the assembly line, **aggregation stages** are th
4747
assembly stations, and **operator expressions** are the
4848
specialized tools.
4949

50-
Aggregation Versus Find Operations
51-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50+
Compare Aggregation and Find Operations
51+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5252

5353
You can use find operations to perform the following actions:
5454

@@ -82,20 +82,46 @@ Consider the following limitations when performing aggregation operations:
8282
</reference/operator/aggregation/graphLookup/>` stage has a strict
8383
memory limit of 100 megabytes and ignores the ``allowDiskUse`` option.
8484

85-
.. _php-aggregation-example:
85+
Aggregation APIs
86+
----------------
8687

87-
Aggregation Example
88-
-------------------
88+
The {+library-short+} provides the following APIs to create aggregation
89+
pipelines:
8990

90-
.. note::
91+
- :ref:`php-aggregation-array-api`: Create aggregation pipelines by
92+
passing arrays that specify the aggregation operators and parameters
93+
- :ref:`php-aggregation-builder-api`: Create aggregation pipelines by using native
94+
classes and methods to make your application more type-safe and debuggable
95+
96+
The following sections describe each API and provide examples for
97+
creating aggregation pipelines.
98+
99+
.. _php-aggregation-array-api:
91100

92-
The examples in this guide use the ``restaurants`` collection in the ``sample_restaurants``
93-
database from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
94-
free MongoDB Atlas cluster and load the sample datasets, see the :atlas:`Get Started with Atlas
95-
</getting-started>` guide.
101+
Array API
102+
---------
96103

97-
To perform an aggregation, pass an array containing the pipeline stages to
98-
the ``MongoDB\Collection::aggregate()`` method.
104+
To perform an aggregation, pass an array containing the pipeline stages
105+
as BSON documents to the ``MongoDB\Collection::aggregate()`` method, as
106+
shown in the following code:
107+
108+
.. code-block:: php
109+
110+
$pipeline = [
111+
['<operator>' => <parameters>],
112+
['<operator>' => <parameters>],
113+
...
114+
];
115+
116+
$cursor = $collection->aggregate($pipeline);
117+
118+
The examples in this section use the ``restaurants`` collection in the ``sample_restaurants``
119+
database from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
120+
free MongoDB Atlas cluster and load the sample datasets, see the :atlas:`Get Started with Atlas
121+
</getting-started>` guide.
122+
123+
Filter and Group Example
124+
~~~~~~~~~~~~~~~~~~~~~~~~
99125

100126
The following code example produces a count of the number of bakeries in each borough
101127
of New York. To do so, it uses an aggregation pipeline that contains the following stages:
@@ -110,9 +136,9 @@ of New York. To do so, it uses an aggregation pipeline that contains the followi
110136
.. io-code-block::
111137
:copyable:
112138

113-
.. input:: /includes/aggregation/aggregation.php
114-
:start-after: start-match-group
115-
:end-before: end-match-group
139+
.. input:: /includes/aggregation.php
140+
:start-after: start-array-match-group
141+
:end-before: end-array-match-group
116142
:language: php
117143
:dedent:
118144

@@ -141,14 +167,14 @@ and pass the database, collection, and pipeline stages as parameters. Then, pass
141167
``MongoDB\Operation\Aggregate`` object to the ``MongoDB\Collection::explain()`` method.
142168

143169
The following example instructs MongoDB to explain the aggregation operation
144-
from the preceding :ref:`php-aggregation-example`:
170+
from the preceding section:
145171

146172
.. io-code-block::
147173
:copyable:
148174

149-
.. input:: /includes/aggregation/aggregation.php
150-
:start-after: start-explain
151-
:end-before: end-explain
175+
.. input:: /includes/aggregation.php
176+
:start-after: start-array-explain
177+
:end-before: end-array-explain
152178
:language: php
153179
:dedent:
154180

@@ -161,6 +187,162 @@ from the preceding :ref:`php-aggregation-example`:
161187
"maxIndexedAndSolutionsReached":false,"maxScansToExplodeReached":false,"winningPlan":{
162188
... }
163189

190+
.. _php-aggregation-builder-api:
191+
192+
Aggregation Builder
193+
-------------------
194+
195+
To create an aggregation pipeline by using the Aggregation Builder,
196+
perform the following actions:
197+
198+
#. Create a ``Pipeline`` class instance to initialize the pipeline
199+
200+
#. Within the ``Pipeline`` instance, call an operator method from the ``Stage``
201+
builder class to create that type of aggregation stage
202+
203+
#. Within the body of the ``Stage`` method, use methods from other
204+
builder classes such as ``Query``, ``Expression``, or ``Accumulator``
205+
to express your aggregation specifications
206+
207+
The following code demonstrates the template for constructing
208+
aggregation pipelines:
209+
210+
.. code-block:: php
211+
212+
$pipeline = new Pipeline(
213+
Stage::<operator method>(
214+
<stage specification>
215+
),
216+
Stage::<operator method>(
217+
<stage specification>
218+
),
219+
...
220+
);
221+
222+
$cursor = $collection->aggregate(iterator_to_array($pipeline));
223+
224+
.. note::
225+
226+
The preceding code uses the ``iterator_to_array()`` method to
227+
convert the ``Pipeline`` instance into an array. You must call this method
228+
on your ``Pipeline`` before passing it to the ``aggregate()`` method.
229+
230+
The examples in this section are adapted from the {+mdb-server+} manual.
231+
Each example provides a link to the sample data that you can insert into
232+
your database to test the aggregation operation.
233+
234+
Filter and Group Example
235+
~~~~~~~~~~~~~~~~~~~~~~~~
236+
237+
This example uses the sample data given in the :manual:`Calculate Count,
238+
Sum, and Average </reference/operator/aggregation/group/#calculate-count--sum--and-average>`
239+
section of the ``$group`` stage reference in the Server manual.
240+
241+
The following code example calculates the total sales amount, average
242+
sales quantity, and sale count for each day in the year 2014. To do so,
243+
it uses an aggregation pipeline that contains the following stages:
244+
245+
- :manual:`$match </reference/operator/aggregation/match/>` stage to
246+
filter for documents that contain a ``date`` field in which the year is
247+
2014
248+
249+
- :manual:`$group </reference/operator/aggregation/group/>` stage to
250+
group the documents by date and calculate the total sale amount,
251+
average quantity, and total count for each group
252+
253+
- :manual:`$sort </reference/operator/aggregation/sort/>` stage to
254+
sort the results by the total sale amount for each group in descending
255+
order
256+
257+
.. io-code-block::
258+
:copyable:
259+
260+
.. input:: /includes/aggregation.php
261+
:start-after: start-builder-match-group
262+
:end-before: end-builder-match-group
263+
:language: php
264+
:dedent:
265+
266+
.. output::
267+
:visible: false
268+
269+
{"_id":"2014-04-04","totalSaleAmount":{"$numberDecimal":"200"},"averageQuantity":15,"count":2}
270+
{"_id":"2014-03-15","totalSaleAmount":{"$numberDecimal":"50"},"averageQuantity":10,"count":1}
271+
{"_id":"2014-03-01","totalSaleAmount":{"$numberDecimal":"40"},"averageQuantity":1.5,"count":2}
272+
273+
Unwind Embedded Arrays Example
274+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275+
276+
This example uses the sample data given in the :manual:`Unwind Embedded Arrays
277+
</reference/operator/aggregation/unwind/#unwind-embedded-arrays>`
278+
section of the ``$unwind`` stage reference in the Server manual.
279+
280+
The following code example groups sold items by their tags and
281+
calculates the total sales amount for each tag. To do so,
282+
it uses an aggregation pipeline that contains the following stages:
283+
284+
- :manual:`$unwind </reference/operator/aggregation/unwind/>` stage to
285+
output a separate document for each element in the ``items`` array
286+
287+
- :manual:`$unwind </reference/operator/aggregation/unwind/>` stage to
288+
output a separate document for each element in the ``items.tags`` arrays
289+
290+
- :manual:`$group </reference/operator/aggregation/group/>` stage to
291+
group the documents by the tag value and calculates the total sales
292+
amount of items that have each tag
293+
294+
.. io-code-block::
295+
:copyable:
296+
297+
.. input:: /includes/aggregation.php
298+
:start-after: start-builder-unwind
299+
:end-before: end-builder-unwind
300+
:language: php
301+
:dedent:
302+
303+
.. output::
304+
:visible: false
305+
306+
{"_id":"office","totalSalesAmount":{"$numberDecimal":"1019.60"}}
307+
{"_id":"school","totalSalesAmount":{"$numberDecimal":"104.85"}}
308+
{"_id":"stationary","totalSalesAmount":{"$numberDecimal":"264.45"}}
309+
{"_id":"electronics","totalSalesAmount":{"$numberDecimal":"800.00"}}
310+
{"_id":"writing","totalSalesAmount":{"$numberDecimal":"60.00"}}
311+
312+
Single Equality Join Example
313+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314+
315+
This example uses the sample data given in the :manual:`Perform a Single
316+
Equality Join with $lookup
317+
</reference/operator/aggregation/lookup/#perform-a-single-equality-join-with--lookup>`
318+
section of the ``$lookup`` stage reference in the Server manual.
319+
320+
The following code example joins the documents from the ``orders``
321+
collection with the documents from the ``inventory`` collection by using
322+
the ``item`` field from the ``orders`` collection and the ``sku`` field
323+
from the ``inventory`` collection.
324+
325+
To do so, the example uses an aggregation pipeline that contains a
326+
:manual:`$lookup </reference/operator/aggregation/lookup/>` stage that
327+
specifies the collection to retrieve data from and the local and
328+
foreign field names.
329+
330+
.. io-code-block::
331+
:copyable:
332+
333+
.. input:: /includes/aggregation.php
334+
:start-after: start-builder-lookup
335+
:end-before: end-builder-lookup
336+
:language: php
337+
:dedent:
338+
339+
.. output::
340+
:visible: false
341+
342+
{"_id":1,"item":"almonds","price":12,"quantity":2,"inventory_docs":[{"_id":1,"sku":"almonds","description":"product 1","instock":120}]}
343+
{"_id":2,"item":"pecans","price":20,"quantity":1,"inventory_docs":[{"_id":4,"sku":"pecans","description":"product 4","instock":70}]}
344+
{"_id":3,"inventory_docs":[{"_id":5,"sku":null,"description":"Incomplete"},{"_id":6}]}
345+
164346
Additional Information
165347
----------------------
166348

@@ -169,6 +351,11 @@ pipelines, see `Complex Aggregation Pipelines with Vanilla PHP and MongoDB
169351
<https://www.mongodb.com/developer/products/mongodb/aggregations-php-mongodb/>`__
170352
in the MongoDB Developer Center.
171353

354+
To view more examples of aggregation pipelines built by using the Aggregation
355+
Builder, see the :github:`Stage class test suite
356+
<mongodb/mongo-php-library/tree/{+source-gh-branch+}/tests/Builder/Stage>` in the
357+
{+library-short+} source code on GitHub.
358+
172359
MongoDB Server Manual
173360
~~~~~~~~~~~~~~~~~~~~~
174361

0 commit comments

Comments
 (0)