summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/text.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/text.cpp')
-rw-r--r--src/mongo/db/exec/text.cpp46
1 files changed, 37 insertions, 9 deletions
diff --git a/src/mongo/db/exec/text.cpp b/src/mongo/db/exec/text.cpp
index f698dbd0dc8..726f015bb3e 100644
--- a/src/mongo/db/exec/text.cpp
+++ b/src/mongo/db/exec/text.cpp
@@ -30,8 +30,10 @@
#include <vector>
+#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/filter.h"
#include "mongo/db/exec/index_scan.h"
+#include "mongo/db/exec/or.h"
#include "mongo/db/exec/scoped_timer.h"
#include "mongo/db/exec/text_match.h"
#include "mongo/db/exec/text_or.h"
@@ -60,7 +62,7 @@ TextStage::TextStage(OperationContext* opCtx,
WorkingSet* ws,
const MatchExpression* filter)
: PlanStage(kStageType, opCtx), _params(params) {
- _children.emplace_back(buildTextTree(opCtx, ws, filter));
+ _children.emplace_back(buildTextTree(opCtx, ws, filter, params.wantTextScore));
_specificStats.indexPrefix = _params.indexPrefix;
_specificStats.indexName = _params.index->indexName();
_specificStats.parsedTextQuery = _params.query.toBSON();
@@ -94,10 +96,10 @@ const SpecificStats* TextStage::getSpecificStats() const {
unique_ptr<PlanStage> TextStage::buildTextTree(OperationContext* opCtx,
WorkingSet* ws,
- const MatchExpression* filter) const {
- auto textScorer = make_unique<TextOrStage>(opCtx, _params.spec, ws, filter, _params.index);
-
+ const MatchExpression* filter,
+ bool wantTextScore) const {
// Get all the index scans for each term in our query.
+ std::vector<std::unique_ptr<PlanStage>> indexScanList;
for (const auto& term : _params.query.getTermsForBounds()) {
IndexScanParams ixparams;
@@ -110,14 +112,40 @@ unique_ptr<PlanStage> TextStage::buildTextTree(OperationContext* opCtx,
ixparams.descriptor = _params.index;
ixparams.direction = -1;
- textScorer->addChild(make_unique<IndexScan>(opCtx, ixparams, ws, nullptr));
+ indexScanList.push_back(stdx::make_unique<IndexScan>(opCtx, ixparams, ws, nullptr));
}
- auto matcher =
- make_unique<TextMatchStage>(opCtx, std::move(textScorer), _params.query, _params.spec, ws);
+ // Build the union of the index scans as a TEXT_OR or an OR stage, depending on whether the
+ // projection requires the "textScore" $meta field.
+ std::unique_ptr<PlanStage> textMatchStage;
+ if (wantTextScore) {
+ // We use a TEXT_OR stage to get the union of the results from the index scans and then
+ // compute their text scores. This is a blocking operation.
+ auto textScorer = make_unique<TextOrStage>(opCtx, _params.spec, ws, filter, _params.index);
+
+ textScorer->addChildren(std::move(indexScanList));
+
+ textMatchStage = make_unique<TextMatchStage>(
+ opCtx, std::move(textScorer), _params.query, _params.spec, ws);
+ } else {
+ // Because we don't need the text score, we can use a non-blocking OR stage to get the union
+ // of the index scans.
+ auto textSearcher = make_unique<OrStage>(opCtx, ws, true, filter);
+
+ textSearcher->addChildren(std::move(indexScanList));
+
+ // Unlike the TEXT_OR stage, the OR stage does not fetch the documents that it outputs. We
+ // add our own FETCH stage to satisfy the requirement of the TEXT_MATCH stage that its
+ // WorkingSetMember inputs have fetched data.
+ const MatchExpression* emptyFilter = nullptr;
+ auto fetchStage = make_unique<FetchStage>(
+ opCtx, ws, textSearcher.release(), emptyFilter, _params.index->getCollection());
+
+ textMatchStage = make_unique<TextMatchStage>(
+ opCtx, std::move(fetchStage), _params.query, _params.spec, ws);
+ }
- unique_ptr<PlanStage> treeRoot = std::move(matcher);
- return treeRoot;
+ return textMatchStage;
}
} // namespace mongo