Skip to content

DOCSP-43919: aggregation builder #203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ on:

env:
PHP_VERSION: "8.2"
# TODO: change to "stable" once 1.20.0 is released
# DRIVER_VERSION: "stable"
DRIVER_VERSION: "mongodb/mongo-php-driver@master"
DRIVER_VERSION: "stable"

jobs:
phpcs:
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ on:

env:
PHP_VERSION: "8.2"
# TODO: change to "stable" once 1.20.0 is released
# DRIVER_VERSION: "stable"
DRIVER_VERSION: "mongodb/mongo-php-driver@master"
DRIVER_VERSION: "stable"

jobs:
psalm:
Expand Down
1 change: 1 addition & 0 deletions snooty.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ php-library = "MongoDB PHP Library"
[constants]
php-library = "MongoDB PHP Library"
version = "1.20"
source-gh-branch = "v1.x"
full-version = "{+version+}.0"
extension-short = "PHP extension"
mdb-server = "MongoDB Server"
Expand Down
228 changes: 206 additions & 22 deletions source/aggregation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ The **aggregation pipeline** is the assembly line, **aggregation stages** are th
assembly stations, and **operator expressions** are the
specialized tools.

Aggregation Versus Find Operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compare Aggregation and Find Operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can use find operations to perform the following actions:

Expand All @@ -72,6 +72,7 @@ Consider the following limitations when performing aggregation operations:
- Returned documents cannot violate the
:manual:`BSON document size limit </reference/limits/#mongodb-limit-BSON-Document-Size>`
of 16 megabytes.

- Pipeline stages have a memory limit of 100 megabytes by default. You can exceed this
limit by creating an options array that sets the ``allowDiskUse`` option to ``true``
and passing the array to the ``MongoDB\Collection::aggregate()`` method.
Expand All @@ -82,37 +83,63 @@ Consider the following limitations when performing aggregation operations:
</reference/operator/aggregation/graphLookup/>` stage has a strict
memory limit of 100 megabytes and ignores the ``allowDiskUse`` option.

.. _php-aggregation-example:
Aggregation APIs
----------------

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

- :ref:`php-aggregation-array-api`: Create aggregation pipelines by
passing arrays that specify the aggregation stages.
- :ref:`php-aggregation-builder-api`: Create aggregation pipelines by
using factory methods to make your application more type-safe and debuggable.

The following sections describe each API and provide examples for
creating aggregation pipelines.

.. note::
.. _php-aggregation-array-api:

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

To perform an aggregation, pass an array containing the pipeline stages to
the ``MongoDB\Collection::aggregate()`` method.
To perform an aggregation, pass an array containing the pipeline stages
as BSON documents to the ``MongoDB\Collection::aggregate()`` method, as
shown in the following code:

.. code-block:: php

$pipeline = [
['<stage>' => <parameters>],
['<stage>' => <parameters>],
...
];

$cursor = $collection->aggregate($pipeline);

The examples in this section use the ``restaurants`` collection in the ``sample_restaurants``
database from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
free MongoDB Atlas cluster and load the sample datasets, see the :atlas:`Get Started with Atlas
</getting-started>` guide.

Filter and Group Example
~~~~~~~~~~~~~~~~~~~~~~~~

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

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

- :manual:`$group </reference/operator/aggregation/group/>` stage to group the matching
documents by the ``borough`` field, accumulating a count of documents for each distinct
value
#. :manual:`$group </reference/operator/aggregation/group/>` stage to group the matching
documents by the ``borough`` field, accumulating a count of documents for each distinct
value

.. io-code-block::
:copyable:

.. input:: /includes/aggregation/aggregation.php
:start-after: start-match-group
:end-before: end-match-group
:start-after: start-array-match-group
:end-before: end-array-match-group
:language: php
:dedent:

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

The following example instructs MongoDB to explain the aggregation operation
from the preceding :ref:`php-aggregation-example`:
from the preceding section:

.. io-code-block::
:copyable:

.. input:: /includes/aggregation/aggregation.php
:start-after: start-explain
:end-before: end-explain
:start-after: start-array-explain
:end-before: end-array-explain
:language: php
:dedent:

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

.. _php-aggregation-builder-api:

Aggregation Builder
-------------------

To create an aggregation pipeline by using the Aggregation Builder,
perform the following actions:

1. Create an array to store the pipeline stages.

#. For each stage, call the a factory method from the
``Stage`` that shares the same name as your desired aggregation
stage. For example, to create an ``$unwind`` stage, call the
``Stage::unwind()`` method.

#. Within the body of the ``Stage`` method, use methods from other
builder classes such as ``Query``, ``Expression``, or ``Accumulator``
to express your aggregation specifications.

The following code demonstrates the template for constructing
aggregation pipelines:

.. code-block:: php

$pipeline = [
Stage::<factory method>(
<stage specification>
),
Stage::<factory method>(
<stage specification>
),
...
];

$cursor = $collection->aggregate($pipeline);

The examples in this section are adapted from the {+mdb-server+} manual.
Each example provides a link to the sample data that you can insert into
your database to test the aggregation operation.

Filter and Group Example
~~~~~~~~~~~~~~~~~~~~~~~~

This example uses the sample data given in the :manual:`Calculate Count,
Sum, and Average </reference/operator/aggregation/group/#calculate-count--sum--and-average>`
section of the ``$group`` stage reference in the Server manual.

The following code example calculates the total sales amount, average
sales quantity, and sale count for each day in the year 2014. To do so,
it uses an aggregation pipeline that contains the following stages:

1. :manual:`$match </reference/operator/aggregation/match/>` stage to
filter for documents that contain a ``date`` field in which the year is
2014

#. :manual:`$group </reference/operator/aggregation/group/>` stage to
group the documents by date and calculate the total sales amount,
average sales quantity, and sale count for each group

#. :manual:`$sort </reference/operator/aggregation/sort/>` stage to
sort the results by the total sale amount for each group in descending
order

.. io-code-block::
:copyable:

.. input:: /includes/aggregation/aggregation.php
:start-after: start-builder-match-group
:end-before: end-builder-match-group
:language: php
:dedent:

.. output::
:visible: false

{"_id":"2014-04-04","totalSaleAmount":{"$numberDecimal":"200"},"averageQuantity":15,"count":2}
{"_id":"2014-03-15","totalSaleAmount":{"$numberDecimal":"50"},"averageQuantity":10,"count":1}
{"_id":"2014-03-01","totalSaleAmount":{"$numberDecimal":"40"},"averageQuantity":1.5,"count":2}

Unwind Embedded Arrays Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This example uses the sample data given in the :manual:`Unwind Embedded Arrays
</reference/operator/aggregation/unwind/#unwind-embedded-arrays>`
section of the ``$unwind`` stage reference in the Server manual.

The following code example groups sold items by their tags and
calculates the total sales amount for each tag. To do so,
it uses an aggregation pipeline that contains the following stages:

1. :manual:`$unwind </reference/operator/aggregation/unwind/>` stage to
output a separate document for each element in the ``items`` array

#. :manual:`$unwind </reference/operator/aggregation/unwind/>` stage to
output a separate document for each element in the ``items.tags`` arrays

#. :manual:`$group </reference/operator/aggregation/group/>` stage to
group the documents by the tag value and calculate the total sales
amount of items that have each tag

.. io-code-block::
:copyable:

.. input:: /includes/aggregation/aggregation.php
:start-after: start-builder-unwind
:end-before: end-builder-unwind
:language: php
:dedent:

.. output::
:visible: false

{"_id":"office","totalSalesAmount":{"$numberDecimal":"1019.60"}}
{"_id":"school","totalSalesAmount":{"$numberDecimal":"104.85"}}
{"_id":"stationary","totalSalesAmount":{"$numberDecimal":"264.45"}}
{"_id":"electronics","totalSalesAmount":{"$numberDecimal":"800.00"}}
{"_id":"writing","totalSalesAmount":{"$numberDecimal":"60.00"}}

Single Equality Join Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This example uses the sample data given in the :manual:`Perform a Single
Equality Join with $lookup
</reference/operator/aggregation/lookup/#perform-a-single-equality-join-with--lookup>`
section of the ``$lookup`` stage reference in the Server manual.

The following code example joins the documents from the ``orders``
collection with the documents from the ``inventory`` collection by using
the ``item`` field from the ``orders`` collection and the ``sku`` field
from the ``inventory`` collection.

To do so, the example uses an aggregation pipeline that contains a
:manual:`$lookup </reference/operator/aggregation/lookup/>` stage that
specifies the collection to retrieve data from and the local and
foreign field names.

.. io-code-block::
:copyable:

.. input:: /includes/aggregation/aggregation.php
:start-after: start-builder-lookup
:end-before: end-builder-lookup
:language: php
:dedent:

.. output::
:visible: false

{"_id":1,"item":"almonds","price":12,"quantity":2,"inventory_docs":[{"_id":1,"sku":"almonds","description":"product 1","instock":120}]}
{"_id":2,"item":"pecans","price":20,"quantity":1,"inventory_docs":[{"_id":4,"sku":"pecans","description":"product 4","instock":70}]}
{"_id":3,"inventory_docs":[{"_id":5,"sku":null,"description":"Incomplete"},{"_id":6}]}

Additional Information
----------------------

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

To view more examples of aggregation pipelines built by using the Aggregation
Builder, see the :github:`Stage class test suite
<mongodb/mongo-php-library/tree/{+source-gh-branch+}/tests/Builder/Stage>` in the
{+library-short+} source code on GitHub.

MongoDB Server Manual
~~~~~~~~~~~~~~~~~~~~~

Expand Down
9 changes: 4 additions & 5 deletions source/aggregation/atlas-search.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ Overview

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

.. note:: Deployment Compatibility

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

1. Create an array to store the pipeline stages
1. Create an array to store the pipeline stages.

#. Call the ``Stage::search()`` method to create the Atlas Search stage
#. Call the ``Stage::search()`` method to create the Atlas Search stage.

#. Within the body of the ``search()`` method, use methods from the
``Search`` builder class to construct your Search query criteria
``Search`` builder class to construct your Search query criteria.

The following code demonstrates the template for constructing basic Atlas Search
queries:
Expand Down
9 changes: 4 additions & 5 deletions source/aggregation/vector-search.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ Overview

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

.. note:: Deployment Compatibility

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

1. Create an array to store the pipeline stages
1. Create an array to store the pipeline stages.

#. Call the ``Stage::vectorSearch()`` method to create the Atlas Vector
Search stage
Search stage.

#. Within the body of the ``vectorSearch()`` method, specify the
criteria for your vector query
criteria for your vector query.

The following code demonstrates the template for constructing basic Atlas Search
queries:
Expand Down
Loading
Loading