diff options
author | Mathias Stearn <mathias@10gen.com> | 2012-10-18 17:21:45 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2012-11-05 13:03:26 -0500 |
commit | d8384a53036b471099b8d293ac21b7bd4809df33 (patch) | |
tree | d56927c99d605bcb6ea6fdff4ca81e267b4b11f9 /src/mongo/db/pipeline/pipeline.cpp | |
parent | d5390644810ab9a79146b62a02e46f2854cc340b (diff) | |
download | mongo-d8384a53036b471099b8d293ac21b7bd4809df33.tar.gz |
SERVER-7408 Correctly handle $skip and $limit in sharded agg
This bug only comes up if the first $skip or $limit precedes the first
$sort or $limit. This is very rare, but should still be handled
correctly.
Diffstat (limited to 'src/mongo/db/pipeline/pipeline.cpp')
-rw-r--r-- | src/mongo/db/pipeline/pipeline.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp index b1ab0c0dbe3..b7ebf86272c 100644 --- a/src/mongo/db/pipeline/pipeline.cpp +++ b/src/mongo/db/pipeline/pipeline.cpp @@ -218,6 +218,35 @@ namespace mongo { } } + /* Move limits in front of skips. This is more optimal for sharding + * since currently, we can only split the pipeline at a single source + * and it is better to limit the results coming from each shard + */ + for(int i = pSourceVector->size() - 1; i >= 1 /* not looking at 0 */; i--) { + DocumentSourceLimit* limit = + dynamic_cast<DocumentSourceLimit*>((*pSourceVector)[i].get()); + DocumentSourceSkip* skip = + dynamic_cast<DocumentSourceSkip*>((*pSourceVector)[i-1].get()); + if (limit && skip) { + // Increase limit by skip since the skipped docs now pass through the $limit + limit->setLimit(limit->getLimit() + skip->getSkip()); + swap((*pSourceVector)[i], (*pSourceVector)[i-1]); + + // Start at back again. This is needed to handle cases with more than 1 $limit + // (S means skip, L means limit) + // + // These two would work without second pass (assuming back to front ordering) + // SL -> LS + // SSL -> LSS + // + // The following cases need a second pass to handle the second limit + // SLL -> LLS + // SSLL -> LLSS + // SLSL -> LLSS + i = pSourceVector->size(); // decremented before next pass + } + } + /* Coalesce adjacent filters where possible. Two adjacent filters are equivalent to one filter whose predicate is the conjunction of |