@@ -50,47 +50,58 @@ Pipeline Sequence Optimization
50
50
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51
51
52
52
For an aggregation pipeline that contains a projection stage
53
- (:pipeline:`$project` or :pipeline:`$unset` or
54
- :pipeline:`$addFields` or :pipeline:`$set`) followed by a
55
- :pipeline:`$match` stage, MongoDB moves any filters in the
56
- :pipeline:`$match` stage that do not require values computed in the
57
- projection stage to a new :pipeline:`$match` stage before the
53
+ (:pipeline:`$addFields`, :pipeline:`$project`, :pipeline:`$set`, or
54
+ :pipeline:`$unset`) followed by a :pipeline:`$match` stage, MongoDB
55
+ moves any filters in the ``$match`` stage that do not require values
56
+ computed in the projection stage to a new ``$match`` stage before the
58
57
projection.
59
58
60
- If an aggregation pipeline contains multiple projection and/or
61
- :pipeline:`$match` stages, MongoDB performs this optimization for each
62
- :pipeline:`$match` stage, moving each :pipeline:` $match` filter before
63
- all projection stages that the filter does not depend on.
59
+ If an aggregation pipeline contains multiple projection or ``$match``
60
+ stages, MongoDB performs this optimization for each ``$match`` stage,
61
+ moving each `` $match`` filter before all projection stages that the
62
+ filter does not depend on.
64
63
65
- Consider a pipeline of the following stages:
64
+ Consider a pipeline with the following stages:
66
65
67
66
.. code-block:: javascript
68
- :emphasize-lines: 9-14
67
+ :emphasize-lines: 18-23
69
68
70
- { $addFields: {
71
- maxTime: { $max: "$times" },
72
- minTime: { $min: "$times" }
73
- } },
74
- { $project: {
75
- _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
76
- avgTime: { $avg: ["$maxTime", "$minTime"] }
77
- } },
78
- { $match: {
79
- name: "Joe Schmoe",
80
- maxTime: { $lt: 20 },
81
- minTime: { $gt: 5 },
82
- avgTime: { $gt: 7 }
83
- } }
84
-
85
- The optimizer breaks up the :pipeline:`$match` stage into four
86
- individual filters, one for each key in the :pipeline:`$match` query
87
- document. The optimizer then moves each filter before as many projection
88
- stages as possible, creating new :pipeline:`$match` stages as needed.
89
- Given this example, the optimizer produces the following *optimized*
90
- pipeline:
69
+ {
70
+ $addFields: {
71
+ maxTime: { $max: "$times" },
72
+ minTime: { $min: "$times" }
73
+ }
74
+ },
75
+ {
76
+ $project: {
77
+ _id: 1,
78
+ name: 1,
79
+ times: 1,
80
+ maxTime: 1,
81
+ minTime: 1,
82
+ avgTime: { $avg: ["$maxTime", "$minTime"] }
83
+ }
84
+ },
85
+ {
86
+ $match: {
87
+ name: "Joe Schmoe",
88
+ maxTime: { $lt: 20 },
89
+ minTime: { $gt: 5 },
90
+ avgTime: { $gt: 7 }
91
+ }
92
+ }
93
+
94
+ The optimizer breaks up the ``$match`` stage into four individual
95
+ filters, one for each key in the ``$match`` query document. The
96
+ optimizer then moves each filter before as many projection stages as
97
+ possible, creating new ``$match`` stages as needed.
98
+
99
+ Given this example, the optimizer automatically produces the following
100
+ *optimized* pipeline:
91
101
92
102
.. code-block:: javascript
93
103
:emphasize-lines: 1, 6, 11
104
+ :copyable: false
94
105
95
106
{ $match: { name: "Joe Schmoe" } },
96
107
{ $addFields: {
@@ -104,6 +115,14 @@ pipeline:
104
115
} },
105
116
{ $match: { avgTime: { $gt: 7 } } }
106
117
118
+ .. note::
119
+
120
+ The optimized pipeline is not intended to be run manually. The
121
+ original and optimized pipelines return the same results.
122
+
123
+ You can see the optimized pipeline in the :ref:`explain plan
124
+ <example-aggregate-method-explain-option>`.
125
+
107
126
The :pipeline:`$match` filter ``{ avgTime: { $gt: 7 } }`` depends on the
108
127
:pipeline:`$project` stage to compute the ``avgTime`` field. The
109
128
:pipeline:`$project` stage is the last projection stage in this
@@ -121,13 +140,10 @@ use any values computed in either the :pipeline:`$project` or
121
140
:pipeline:`$addFields` stages so it was moved to a new
122
141
:pipeline:`$match` stage before both of the projection stages.
123
142
124
- .. note::
125
- After optimization, the filter ``{ name: "Joe Schmoe" }`` is in
126
- a :pipeline:`$match` stage at the beginning of the pipeline. This has
127
- the added benefit of allowing the aggregation to use an index on the
128
- ``name`` field when initially querying the collection.
129
- See :ref:`aggregation-pipeline-operators-and-performance` for more
130
- information.
143
+ After optimization, the filter ``{ name: "Joe Schmoe" }`` is in a
144
+ :pipeline:`$match` stage at the beginning of the pipeline. This has the
145
+ added benefit of allowing the aggregation to use an index on the
146
+ ``name`` field when initially querying the collection.
131
147
132
148
.. _agg-sort-match-optimization:
133
149
@@ -505,4 +521,4 @@ MongoDB increases the :pipeline:`$limit` amount with the reordering.
505
521
.. seealso::
506
522
507
523
:method:`explain <db.collection.aggregate()>` option in the
508
- :method:`db.collection.aggregate()`
524
+ :method:`db.collection.aggregate()`
0 commit comments