@@ -169,72 +169,32 @@ The optimizer can add the same :pipeline:`$match` stage before the
169
169
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } },
170
170
{ $match: { year: 2014, category: { $ne: "Z" } } }
171
171
172
- .. _agg-skip-limit -optimization:
172
+ .. _agg-project-skip -optimization:
173
173
174
- ``$skip`` + ``$limit`` Sequence Optimization
175
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176
-
177
- When you have a sequence with :pipeline:`$skip` followed by a
178
- :pipeline:`$limit`, the :pipeline:`$limit` moves before the
179
- :pipeline:`$skip`. With the reordering, the :pipeline:`$limit` value
180
- increases by the :pipeline:`$skip` amount.
181
-
182
- For example, if the pipeline consists of the following stages:
183
-
184
- .. code-block:: javascript
185
-
186
- { $skip: 10 },
187
- { $limit: 5 }
188
-
189
- During the optimization phase, the optimizer transforms the sequence to
190
- the following:
191
-
192
- .. code-block:: javascript
193
-
194
- { $limit: 15 },
195
- { $skip: 10 }
196
-
197
- This optimization allows for more opportunities for
198
- :ref:`agg-sort-limit-coalescence`, such as with ``$sort`` + ``$skip`` +
199
- ``$limit`` sequences. See :ref:`agg-sort-limit-coalescence` for details
200
- on the coalescence and :ref:`agg-sort-skip-limit-sequence` for an
201
- example.
202
-
203
- For aggregation operations on :doc:`sharded collections
204
- <aggregation-pipeline-sharded-collections>`, this optimization reduces
205
- the results returned from each shard.
206
-
207
- .. _agg-project-skip-limit-optimization:
208
-
209
- ``$project`` + ``$skip`` or ``$limit`` Sequence Optimization
210
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174
+ ``$project`` + ``$skip`` Sequence Optimization
175
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211
176
212
177
.. versionadded:: 3.2
213
178
214
- When you have a sequence with :pipeline:`$project` followed by either
215
- :pipeline:`$skip` or :pipeline:`$limit` , the :pipeline:`$skip` or
216
- :pipeline:`$limit` moves before :pipeline:`$project`. For example, if
179
+ When you have a sequence with :pipeline:`$project` followed by
180
+ :pipeline:`$skip`, the :pipeline:`$skip`
181
+ moves before :pipeline:`$project`. For example, if
217
182
the pipeline consists of the following stages:
218
183
219
184
.. code-block:: javascript
220
185
221
186
{ $sort: { age : -1 } },
222
187
{ $project: { status: 1, name: 1 } },
223
- { $limit : 5 }
188
+ { $skip : 5 }
224
189
225
190
During the optimization phase, the optimizer transforms the sequence to
226
191
the following:
227
192
228
193
.. code-block:: javascript
229
194
230
195
{ $sort: { age : -1 } },
231
- { $limit: 5 }
232
- { $project: { status: 1, name: 1 } },
233
-
234
- This optimization allows for more opportunities for
235
- :ref:`agg-sort-limit-coalescence`, such as with ``$sort`` + ``$limit``
236
- sequences. See :ref:`agg-sort-limit-coalescence` for details on the
237
- coalescence.
196
+ { $skip: 5 },
197
+ { $project: { status: 1, name: 1 } }
238
198
239
199
.. _aggregation-pipeline-coalescence-optimization:
240
200
@@ -250,14 +210,58 @@ reordering optimization.
250
210
``$sort`` + ``$limit`` Coalescence
251
211
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
252
212
253
- When a :pipeline:`$sort` immediately precedes a :pipeline:`$limit`, the
254
- optimizer can coalesce the :pipeline:`$limit` into the
255
- :pipeline:`$sort`. This allows the sort operation to only maintain the
213
+ .. versionchanged:: 4.0
214
+
215
+ When a :pipeline:`$sort` precedes a :pipeline:`$limit`, the optimizer
216
+ can coalesce the :pipeline:`$limit` into the :pipeline:`$sort` if no
217
+ intervening stages modify the number of documents
218
+ (e.g. :pipeline:`$unwind`, :pipeline:`$group`).
219
+ MongoDB will not coalesce the :pipeline:`$limit` into the
220
+ :pipeline:`$sort` if there are pipeline stages that change the number of
221
+ documents between the :pipeline:`$sort` and :pipeline:`$limit` stages..
222
+
223
+ For example, if the pipeline consists of the following stages:
224
+
225
+ .. code-block:: javascript
226
+
227
+ { $sort : { age : -1 } },
228
+ { $project : { age : 1, status : 1, name : 1 } },
229
+ { $limit: 5 }
230
+
231
+ During the optimization phase, the optimizer coalesces the sequence
232
+ to the following:
233
+
234
+ .. code-block:: javascript
235
+
236
+ {
237
+ "$sort" : {
238
+ "sortKey" : {
239
+ "age" : -1
240
+ },
241
+ "limit" : NumberLong(5)
242
+ }
243
+ },
244
+ { "$project" : {
245
+ "age" : 1,
246
+ "status" : 1,
247
+ "name" : 1
248
+ }
249
+ }
250
+
251
+ This allows the sort operation to only maintain the
256
252
top ``n`` results as it progresses, where ``n`` is the specified limit,
257
253
and MongoDB only needs to store ``n`` items in memory
258
254
[#coalescence-allowDiskUse]_. See :ref:`sort-and-memory` for more
259
255
information.
260
256
257
+ .. admonition:: Sequence Optimization with $skip
258
+
259
+ If there is a :pipeline:`$skip` stage between the :pipeline:`$sort`
260
+ and :pipeline:`$limit` stages, MongoDB will coalesce the
261
+ :pipeline:`$limit` into the :pipeline:`$sort` stage and increase the
262
+ :pipeline:`$limit` value by the :pipeline:`$skip` amount. See
263
+ :ref:`agg-sort-skip-limit-sequence` for an example.
264
+
261
265
.. [#coalescence-allowDiskUse] The optimization will still apply when
262
266
``allowDiskUse`` is ``true`` and the ``n`` items exceed the
263
267
:ref:`aggregation memory limit <agg-memory-restrictions>`.
@@ -378,13 +382,8 @@ option, the ``explain`` output shows the coalesced stage:
378
382
}
379
383
}
380
384
381
- Examples
382
- --------
383
-
384
- The following examples are some sequences that can take advantage of
385
- both sequence reordering and coalescence. Generally, coalescence occurs
386
- *after* any sequence reordering optimization.
387
-
385
+ Example
386
+ -------
388
387
.. _agg-sort-skip-limit-sequence:
389
388
390
389
``$sort`` + ``$skip`` + ``$limit`` Sequence
@@ -399,60 +398,24 @@ A pipeline contains a sequence of :pipeline:`$sort` followed by a
399
398
{ $skip: 10 },
400
399
{ $limit: 5 }
401
400
402
- First, the optimizer performs the :ref:`agg-skip -limit-optimization ` to
401
+ The optimizer performs :ref:`agg-sort -limit-coalescence ` to
403
402
transforms the sequence to the following:
404
403
405
404
.. code-block:: javascript
406
405
407
- { $sort: { age : -1 } },
408
- { $limit: 15 }
409
- { $skip: 10 }
410
-
411
- The :ref:`agg-skip-limit-optimization` increases the :pipeline:`$limit`
412
- amount with the reordering. See :ref:`agg-skip-limit-optimization` for
413
- details.
414
-
415
- The reordered sequence now has :pipeline:`$sort` immediately preceding
416
- the :pipeline:`$limit`, and the pipeline can coalesce the two stages to
417
- decrease memory usage during the sort operation. See
418
- :ref:`agg-sort-limit-coalescence` for more information.
419
-
420
- ``$limit`` + ``$skip`` + ``$limit`` + ``$skip`` Sequence
421
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
422
-
423
- A pipeline contains a sequence of alternating :pipeline:`$limit` and
424
- :pipeline:`$skip` stages:
425
-
426
- .. code-block:: javascript
427
-
428
- { $limit: 100 },
429
- { $skip: 5 },
430
- { $limit: 10 },
431
- { $skip: 2 }
432
-
433
- The :ref:`agg-skip-limit-optimization` reverses the position of the ``{
434
- $skip: 5 }`` and ``{ $limit: 10 }`` stages and increases the limit
435
- amount:
436
-
437
- .. code-block:: javascript
438
-
439
- { $limit: 100 },
440
- { $limit: 15},
441
- { $skip: 5 },
442
- { $skip: 2 }
443
-
444
- The optimizer then coalesces the two :pipeline:`$limit` stages into a
445
- single :pipeline:`$limit` stage and the two :pipeline:`$skip` stages
446
- into a single :pipeline:`$skip` stage. The resulting sequence is the
447
- following:
448
-
449
- .. code-block:: javascript
450
-
451
- { $limit: 15 },
452
- { $skip: 7 }
406
+ {
407
+ "$sort" : {
408
+ "sortKey" : {
409
+ "age" : -1
410
+ },
411
+ "limit" : NumberLong(15)
412
+ }
413
+ },
414
+ {
415
+ "$skip" : NumberLong(10)
416
+ }
453
417
454
- See :ref:`agg-limit-limit-coalescence` and
455
- :ref:`agg-skip-skip-coalescence` for details.
418
+ MongoDB increases the :pipeline:`$limit` amount with the reordering.
456
419
457
420
.. seealso::
458
421
:method:`explain <db.collection.aggregate()>` option in the
0 commit comments