diff options
author | Jacob Evans <jacob.evans@10gen.com> | 2018-10-31 14:47:41 -0400 |
---|---|---|
committer | Jacob Evans <jacob.evans@10gen.com> | 2018-11-07 11:54:09 -0500 |
commit | 7fadb5dc1ddecb37617b2d927960cd15da8172b2 (patch) | |
tree | e0500f06f2daa4e5b3991be2268c231cd8f29d51 /src/mongo/db/pipeline/document_source.cpp | |
parent | 9fb109b1d55374353954b998bd11bcb0d17b6e91 (diff) | |
download | mongo-7fadb5dc1ddecb37617b2d927960cd15da8172b2.tar.gz |
SERVER-28592 Move $sample earlier in the aggregation pipeline
Diffstat (limited to 'src/mongo/db/pipeline/document_source.cpp')
-rw-r--r-- | src/mongo/db/pipeline/document_source.cpp | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/src/mongo/db/pipeline/document_source.cpp b/src/mongo/db/pipeline/document_source.cpp index 28baeed3fce..bb822fc8189 100644 --- a/src/mongo/db/pipeline/document_source.cpp +++ b/src/mongo/db/pipeline/document_source.cpp @@ -34,6 +34,7 @@ #include "mongo/db/matcher/expression_algo.h" #include "mongo/db/pipeline/document_source_match.h" +#include "mongo/db/pipeline/document_source_sample.h" #include "mongo/db/pipeline/document_source_sequential_document_cache.h" #include "mongo/db/pipeline/expression_context.h" #include "mongo/db/pipeline/field_path.h" @@ -210,17 +211,8 @@ StringMap<std::string> computeNewNamesAssumingAnyPathsNotRenamedAreUnmodified( } // namespace -Pipeline::SourceContainer::iterator DocumentSource::optimizeAt( - Pipeline::SourceContainer::iterator itr, Pipeline::SourceContainer* container) { - invariant(*itr == this); - - // If we are at the end of the pipeline, only optimize in the special case of a cache stage. - if (std::next(itr) == container->end()) { - return dynamic_cast<DocumentSourceSequentialDocumentCache*>(this) - ? doOptimizeAt(itr, container) - : container->end(); - } - +bool DocumentSource::pushMatchBefore(Pipeline::SourceContainer::iterator itr, + Pipeline::SourceContainer* container) { auto nextMatch = dynamic_cast<DocumentSourceMatch*>((*std::next(itr)).get()); if (constraints().canSwapWithMatch && nextMatch && !nextMatch->isTextQuery()) { // We're allowed to swap with a $match and the stage after us is a $match. Furthermore, the @@ -241,12 +233,43 @@ Pipeline::SourceContainer::iterator DocumentSource::optimizeAt( container->insert(std::next(itr), std::move(splitMatch.second)); } - // The stage before the new $match may be able to optimize further, if there is such a - // stage. - return std::prev(itr) == container->begin() ? std::prev(itr) - : std::prev(std::prev(itr)); + return true; } } + return false; +} + +bool DocumentSource::pushSampleBefore(Pipeline::SourceContainer::iterator itr, + Pipeline::SourceContainer* container) { + auto nextSample = dynamic_cast<DocumentSourceSample*>((*std::next(itr)).get()); + if (constraints().canSwapWithLimitAndSample && nextSample) { + + container->insert(itr, std::move(nextSample)); + container->erase(std::next(itr)); + + return true; + } + return false; +} + +Pipeline::SourceContainer::iterator DocumentSource::optimizeAt( + Pipeline::SourceContainer::iterator itr, Pipeline::SourceContainer* container) { + invariant(*itr == this); + + // If we are at the end of the pipeline, only optimize in the special case of a cache stage. + if (std::next(itr) == container->end()) { + return dynamic_cast<DocumentSourceSequentialDocumentCache*>(this) + ? doOptimizeAt(itr, container) + : container->end(); + } + + // Attempt to swap 'itr' with a subsequent $match or subsequent $sample. + if (pushMatchBefore(itr, container) || pushSampleBefore(itr, container)) { + // The stage before the pushed before stage may be able to optimize further, if there is + // such a stage. + return std::prev(itr) == container->begin() ? std::prev(itr) : std::prev(std::prev(itr)); + } + return doOptimizeAt(itr, container); } |