Skip to content

Commit bc9c0e2

Browse files
authored
DOCSP-43919: aggregation builder (#203)
* DOCSP-43919: aggregation builder * indentation fix * remov Pipeline type * LM PR fixes 1 * fp fixes * todo fixes * small fixes * JM tech review 1
1 parent d2c1afb commit bc9c0e2

File tree

9 files changed

+305
-48
lines changed

9 files changed

+305
-48
lines changed

.github/workflows/coding-standards.yml

+1-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ on:
88

99
env:
1010
PHP_VERSION: "8.2"
11-
# TODO: change to "stable" once 1.20.0 is released
12-
# DRIVER_VERSION: "stable"
13-
DRIVER_VERSION: "mongodb/mongo-php-driver@master"
11+
DRIVER_VERSION: "stable"
1412

1513
jobs:
1614
phpcs:

.github/workflows/static-analysis.yml

+1-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ on:
1414

1515
env:
1616
PHP_VERSION: "8.2"
17-
# TODO: change to "stable" once 1.20.0 is released
18-
# DRIVER_VERSION: "stable"
19-
DRIVER_VERSION: "mongodb/mongo-php-driver@master"
17+
DRIVER_VERSION: "stable"
2018

2119
jobs:
2220
psalm:

snooty.toml

+1
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

+206-22
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

@@ -72,6 +72,7 @@ Consider the following limitations when performing aggregation operations:
7272
- Returned documents cannot violate the
7373
:manual:`BSON document size limit </reference/limits/#mongodb-limit-BSON-Document-Size>`
7474
of 16 megabytes.
75+
7576
- Pipeline stages have a memory limit of 100 megabytes by default. You can exceed this
7677
limit by creating an options array that sets the ``allowDiskUse`` option to ``true``
7778
and passing the array to the ``MongoDB\Collection::aggregate()`` method.
@@ -82,37 +83,63 @@ Consider the following limitations when performing aggregation operations:
8283
</reference/operator/aggregation/graphLookup/>` stage has a strict
8384
memory limit of 100 megabytes and ignores the ``allowDiskUse`` option.
8485

85-
.. _php-aggregation-example:
86+
Aggregation APIs
87+
----------------
8688

87-
Aggregation Example
88-
-------------------
89+
The {+library-short+} provides the following APIs to create aggregation
90+
pipelines:
91+
92+
- :ref:`php-aggregation-array-api`: Create aggregation pipelines by
93+
passing arrays that specify the aggregation stages.
94+
- :ref:`php-aggregation-builder-api`: Create aggregation pipelines by
95+
using factory methods to make your application more type-safe and debuggable.
96+
97+
The following sections describe each API and provide examples for
98+
creating aggregation pipelines.
8999

90-
.. note::
100+
.. _php-aggregation-array-api:
91101

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.
102+
Array API
103+
---------
96104

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

100127
The following code example produces a count of the number of bakeries in each borough
101128
of New York. To do so, it uses an aggregation pipeline that contains the following stages:
102129

103-
- :manual:`$match </reference/operator/aggregation/match/>` stage to filter for documents
104-
in which the ``cuisine`` field contains the value ``'Bakery'``
130+
1. :manual:`$match </reference/operator/aggregation/match/>` stage to filter for documents
131+
in which the ``cuisine`` field contains the value ``'Bakery'``
105132

106-
- :manual:`$group </reference/operator/aggregation/group/>` stage to group the matching
107-
documents by the ``borough`` field, accumulating a count of documents for each distinct
108-
value
133+
#. :manual:`$group </reference/operator/aggregation/group/>` stage to group the matching
134+
documents by the ``borough`` field, accumulating a count of documents for each distinct
135+
value
109136

110137
.. io-code-block::
111138
:copyable:
112139

113140
.. input:: /includes/aggregation/aggregation.php
114-
:start-after: start-match-group
115-
:end-before: end-match-group
141+
:start-after: start-array-match-group
142+
:end-before: end-array-match-group
116143
:language: php
117144
:dedent:
118145

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

143170
The following example instructs MongoDB to explain the aggregation operation
144-
from the preceding :ref:`php-aggregation-example`:
171+
from the preceding section:
145172

146173
.. io-code-block::
147174
:copyable:
148175

149176
.. input:: /includes/aggregation/aggregation.php
150-
:start-after: start-explain
151-
:end-before: end-explain
177+
:start-after: start-array-explain
178+
:end-before: end-array-explain
152179
:language: php
153180
:dedent:
154181

@@ -161,6 +188,158 @@ from the preceding :ref:`php-aggregation-example`:
161188
"maxIndexedAndSolutionsReached":false,"maxScansToExplodeReached":false,"winningPlan":{
162189
... }
163190

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

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

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

source/aggregation/atlas-search.txt

+4-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ Overview
2222

2323
In this guide, you can learn how to perform searches on your documents
2424
by using the Atlas Search feature. The {+library-short+} allows you to
25-
perform Atlas Search queries by using the :ref:`Aggregation Builder API
26-
<TODO DOCSP-43919>`.
25+
perform Atlas Search queries by using the :ref:`php-aggregation-builder-api`.
2726

2827
.. note:: Deployment Compatibility
2928

@@ -66,12 +65,12 @@ Search queries by using the Aggregation Builder:
6665
To create a ``$search`` stage in your aggregation pipeline, perform the
6766
following actions:
6867

69-
1. Create an array to store the pipeline stages
68+
1. Create an array to store the pipeline stages.
7069

71-
#. Call the ``Stage::search()`` method to create the Atlas Search stage
70+
#. Call the ``Stage::search()`` method to create the Atlas Search stage.
7271

7372
#. Within the body of the ``search()`` method, use methods from the
74-
``Search`` builder class to construct your Search query criteria
73+
``Search`` builder class to construct your Search query criteria.
7574

7675
The following code demonstrates the template for constructing basic Atlas Search
7776
queries:

source/aggregation/vector-search.txt

+4-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ Overview
2222

2323
In this guide, you can learn how to perform searches on your documents
2424
by using the Atlas Vector Search feature. The {+library-short+} allows you to
25-
perform Atlas Vector Search queries by using the :ref:`Aggregation Builder API
26-
<TODO DOCSP-43919>`.
25+
perform Atlas Vector Search queries by using the :ref:`php-aggregation-builder-api`.
2726

2827
.. note:: Deployment Compatibility
2928

@@ -67,13 +66,13 @@ Search queries by using the Aggregation Builder:
6766
To create a ``$vectorSearch`` stage in your aggregation pipeline, perform the
6867
following actions:
6968

70-
1. Create an array to store the pipeline stages
69+
1. Create an array to store the pipeline stages.
7170

7271
#. Call the ``Stage::vectorSearch()`` method to create the Atlas Vector
73-
Search stage
72+
Search stage.
7473

7574
#. Within the body of the ``vectorSearch()`` method, specify the
76-
criteria for your vector query
75+
criteria for your vector query.
7776

7877
The following code demonstrates the template for constructing basic Atlas Search
7978
queries:

0 commit comments

Comments
 (0)