diff options
Diffstat (limited to 'src/mongo/db/query/plan_enumerator.cpp')
| -rw-r--r-- | src/mongo/db/query/plan_enumerator.cpp | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp index 789cd405607..de80606df8d 100644 --- a/src/mongo/db/query/plan_enumerator.cpp +++ b/src/mongo/db/query/plan_enumerator.cpp @@ -579,6 +579,32 @@ bool PlanEnumerator::prepMemo(MatchExpression* node, PrepMemoContext context) { return false; } +void PlanEnumerator::assignToNonMultikeyMandatoryIndex( + const IndexEntry& index, + const std::vector<MatchExpression*>& predsOverLeadingField, + const IndexToPredMap& idxToNotFirst, + OneIndexAssignment* indexAssign) { + // Text indexes are typically multikey because there is an index key for each token in the + // source text. However, the leading and trailing non-text fields of the index cannot be + // multikey. As a result, we should use non-multikey predicate assignment rules for such + // indexes. + invariant(!index.multikey || index.type == IndexType::INDEX_TEXT); + + // Since the index is not multikey, all predicates over the leading field can be assigned. + indexAssign->preds = predsOverLeadingField; + + // Since everything in assign.preds prefixes the index, they all go at position '0' in the + // index, the first position. + indexAssign->positions.resize(indexAssign->preds.size(), 0); + + // And now we begin compound analysis. Find everything that could use assign.index but isn't a + // pred over the first field of that index. + auto compIt = idxToNotFirst.find(indexAssign->index); + if (compIt != idxToNotFirst.end()) { + compound(compIt->second, index, indexAssign); + } +} + bool PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, const IndexToPredMap& idxToNotFirst, MatchExpression* mandatoryPred, @@ -613,7 +639,12 @@ bool PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, const vector<MatchExpression*>& predsOverLeadingField = it->second; - if (thisIndex.multikey && !thisIndex.multikeyPaths.empty()) { + // Text indexes should be treated like non-multikey indexes, since the non-text fields are + // prohibited from containing arrays. + if (thisIndex.type == IndexType::INDEX_TEXT) { + assignToNonMultikeyMandatoryIndex( + thisIndex, predsOverLeadingField, idxToNotFirst, &indexAssign); + } else if (thisIndex.multikey && !thisIndex.multikeyPaths.empty()) { // 2dsphere indexes are the only special index type that should ever have path-level // multikey information. invariant(INDEX_2DSPHERE == thisIndex.type); @@ -719,22 +750,9 @@ bool PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, } } } else { - // For non-multikey, we don't have to do anything too special. - // Just assign all "first" predicates and try to compound like usual. - indexAssign.preds = it->second; - - // Since everything in assign.preds prefixes the index, they all go - // at position '0' in the index, the first position. - indexAssign.positions.resize(indexAssign.preds.size(), 0); - - // And now we begin compound analysis. - - // Find everything that could use assign.index but isn't a pred over - // the first field of that index. - IndexToPredMap::const_iterator compIt = idxToNotFirst.find(indexAssign.index); - if (compIt != idxToNotFirst.end()) { - compound(compIt->second, thisIndex, &indexAssign); - } + // The index is not multikey. + assignToNonMultikeyMandatoryIndex( + thisIndex, predsOverLeadingField, idxToNotFirst, &indexAssign); } // The mandatory predicate must be assigned. |
