diff options
author | Alberto Massari <alberto.massari@mongodb.com> | 2022-12-21 19:56:54 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-12-21 21:14:53 +0000 |
commit | 5977e706431fd5705b59115ec0e0d2d7a2203246 (patch) | |
tree | 2161b9d853c2e7453a19d12b88bd39bc9bf87dd5 /src/mongo/db/query/collection_query_info.cpp | |
parent | 9ac3279cc3459b31a597ed4659e07ad93f073d8f (diff) | |
download | mongo-5977e706431fd5705b59115ec0e0d2d7a2203246.tar.gz |
SERVER-65364 Allow fine-grained selection of indexes to update
Diffstat (limited to 'src/mongo/db/query/collection_query_info.cpp')
-rw-r--r-- | src/mongo/db/query/collection_query_info.cpp | 136 |
1 files changed, 71 insertions, 65 deletions
diff --git a/src/mongo/db/query/collection_query_info.cpp b/src/mongo/db/query/collection_query_info.cpp index 55261978b21..1f689e766db 100644 --- a/src/mongo/db/query/collection_query_info.cpp +++ b/src/mongo/db/query/collection_query_info.cpp @@ -118,78 +118,84 @@ const UpdateIndexData& CollectionQueryInfo::getIndexKeys(OperationContext* opCtx return _indexedPaths; } -void CollectionQueryInfo::computeIndexKeys(OperationContext* opCtx, const CollectionPtr& coll) { - _indexedPaths.clear(); +void CollectionQueryInfo::computeUpdateIndexData(const IndexCatalogEntry* entry, + const IndexAccessMethod* accessMethod, + UpdateIndexData* outData) { + const IndexDescriptor* descriptor = entry->descriptor(); + if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD); + isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) { + // Obtain the projection used by the $** index's key generator. + const auto* pathProj = isWildcard + ? static_cast<const IndexPathProjection*>( + static_cast<const WildcardAccessMethod*>(accessMethod)->getWildcardProjection()) + : static_cast<const IndexPathProjection*>( + static_cast<const ColumnStoreAccessMethod*>(accessMethod) + ->getColumnstoreProjection()); + // If the projection is an exclusion, then we must check the new document's keys on all + // updates, since we do not exhaustively know the set of paths to be indexed. + if (pathProj->exec()->getType() == + TransformerInterface::TransformerType::kExclusionProjection) { + outData->allPathsIndexed(); + } else { + // If a subtree was specified in the keyPattern, or if an inclusion projection is + // present, then we need only index the path(s) preserved by the projection. + const auto& exhaustivePaths = pathProj->exhaustivePaths(); + invariant(exhaustivePaths); + for (const auto& path : *exhaustivePaths) { + outData->addPath(path); + } + } + } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) { + fts::FTSSpec ftsSpec(descriptor->infoObj()); - auto it = coll->getIndexCatalog()->getIndexIterator( - opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished); - while (it->more()) { - const IndexCatalogEntry* entry = it->next(); - const IndexDescriptor* descriptor = entry->descriptor(); - const IndexAccessMethod* iam = entry->accessMethod(); - - if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD); - isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) { - // Obtain the projection used by the $** index's key generator. - const auto* pathProj = isWildcard - ? static_cast<const IndexPathProjection*>( - static_cast<const WildcardAccessMethod*>(iam)->getWildcardProjection()) - : static_cast<const IndexPathProjection*>( - static_cast<const ColumnStoreAccessMethod*>(iam)->getColumnstoreProjection()); - // If the projection is an exclusion, then we must check the new document's keys on all - // updates, since we do not exhaustively know the set of paths to be indexed. - if (pathProj->exec()->getType() == - TransformerInterface::TransformerType::kExclusionProjection) { - _indexedPaths.allPathsIndexed(); - } else { - // If a subtree was specified in the keyPattern, or if an inclusion projection is - // present, then we need only index the path(s) preserved by the projection. - const auto& exhaustivePaths = pathProj->exhaustivePaths(); - invariant(exhaustivePaths); - for (const auto& path : *exhaustivePaths) { - _indexedPaths.addPath(path); - } + if (ftsSpec.wildcard()) { + outData->allPathsIndexed(); + } else { + for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) { + outData->addPath(FieldRef(ftsSpec.extraBefore(i))); } - } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) { - fts::FTSSpec ftsSpec(descriptor->infoObj()); - - if (ftsSpec.wildcard()) { - _indexedPaths.allPathsIndexed(); - } else { - for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) { - _indexedPaths.addPath(FieldRef(ftsSpec.extraBefore(i))); - } - for (fts::Weights::const_iterator it = ftsSpec.weights().begin(); - it != ftsSpec.weights().end(); - ++it) { - _indexedPaths.addPath(FieldRef(it->first)); - } - for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) { - _indexedPaths.addPath(FieldRef(ftsSpec.extraAfter(i))); - } - // Any update to a path containing "language" as a component could change the - // language of a subdocument. Add the override field as a path component. - _indexedPaths.addPathComponent(ftsSpec.languageOverrideField()); + for (fts::Weights::const_iterator it = ftsSpec.weights().begin(); + it != ftsSpec.weights().end(); + ++it) { + outData->addPath(FieldRef(it->first)); } - } else { - BSONObj key = descriptor->keyPattern(); - BSONObjIterator j(key); - while (j.more()) { - BSONElement e = j.next(); - _indexedPaths.addPath(FieldRef(e.fieldName())); + for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) { + outData->addPath(FieldRef(ftsSpec.extraAfter(i))); } + // Any update to a path containing "language" as a component could change the + // language of a subdocument. Add the override field as a path component. + outData->addPathComponent(ftsSpec.languageOverrideField()); + } + } else { + BSONObj key = descriptor->keyPattern(); + BSONObjIterator j(key); + while (j.more()) { + BSONElement e = j.next(); + outData->addPath(FieldRef(e.fieldName())); } + } - // handle partial indexes - const MatchExpression* filter = entry->getFilterExpression(); - if (filter) { - stdx::unordered_set<std::string> paths; - QueryPlannerIXSelect::getFields(filter, &paths); - for (auto it = paths.begin(); it != paths.end(); ++it) { - _indexedPaths.addPath(FieldRef(*it)); - } + // handle partial indexes + const MatchExpression* filter = entry->getFilterExpression(); + if (filter) { + stdx::unordered_set<std::string> paths; + QueryPlannerIXSelect::getFields(filter, &paths); + for (auto it = paths.begin(); it != paths.end(); ++it) { + outData->addPath(FieldRef(*it)); } } +} + +void CollectionQueryInfo::computeUpdateIndexData(OperationContext* opCtx, + const CollectionPtr& coll) { + _indexedPaths.clear(); + + auto it = coll->getIndexCatalog()->getIndexIterator( + opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished); + while (it->more()) { + const IndexCatalogEntry* entry = it->next(); + computeUpdateIndexData(entry, entry->accessMethod(), &_indexedPaths); + } _keysComputed = true; } @@ -261,7 +267,7 @@ void CollectionQueryInfo::init(OperationContext* opCtx, const CollectionPtr& col void CollectionQueryInfo::rebuildIndexData(OperationContext* opCtx, const CollectionPtr& coll) { _keysComputed = false; - computeIndexKeys(opCtx, coll); + computeUpdateIndexData(opCtx, coll); updatePlanCacheIndexEntries(opCtx, coll); } |