@@ -158,28 +158,28 @@ static std::pair<IndexDefinitions, MultikeynessTrie> buildIndexSpecsOptimizer(
158158
159159 std::pair<IndexDefinitions, MultikeynessTrie> result;
160160 std::string indexHintName;
161- bool skipAllIndexes = false ;
161+
162+ // True if the query has a $natural hint, indicating that we must use a collection scan.
163+ bool hasNaturalHint = false ;
164+
162165 if (indexHint) {
163166 const BSONElement element = indexHint->firstElement ();
164167 const StringData fieldName = element.fieldNameStringData ();
165- if (fieldName == " $natural " _sd ) {
168+ if (fieldName == query_request_helper:: kNaturalSortField ) {
166169 // Do not add indexes.
167- skipAllIndexes = true ;
170+ hasNaturalHint = true ;
168171 } else if (fieldName == " $hint" _sd && element.type () == BSONType::String) {
169172 indexHintName = element.valueStringData ().toString ();
170173 }
171174
172- disableScan = !skipAllIndexes ;
175+ disableScan = !hasNaturalHint ;
173176 }
174177
175178 const IndexCatalog& indexCatalog = *collection->getIndexCatalog ();
176179
177180 auto indexIterator =
178181 indexCatalog.getIndexIterator (opCtx, IndexCatalog::InclusionPolicy::kReady );
179182
180- const bool queryHasNaturalHint = indexHint && !indexHint->isEmpty () &&
181- indexHint->firstElementFieldNameStringData () == query_request_helper::kNaturalSortField ;
182-
183183 while (indexIterator->more ()) {
184184 const IndexCatalogEntry& catalogEntry = *indexIterator->next ();
185185 const IndexDescriptor& descriptor = *catalogEntry.descriptor ();
@@ -196,32 +196,25 @@ static std::pair<IndexDefinitions, MultikeynessTrie> buildIndexSpecsOptimizer(
196196 continue ;
197197 }
198198
199- // If there is a $natural hint, we should not assert here as we will not use the index.
200- const bool isSpecialIndex =
201- descriptor.infoObj ().hasField (IndexDescriptor::kExpireAfterSecondsFieldName ) ||
199+ // Check for special indexes. We do not want to try to build index metadata for a special
200+ // index (since we do not support those yet in CQF) but we should allow the query to go
201+ // through CQF if there is a $natural hint.
202+ if (descriptor.infoObj ().hasField (IndexDescriptor::kExpireAfterSecondsFieldName ) ||
202203 descriptor.isSparse () || descriptor.getIndexType () != IndexType::INDEX_BTREE ||
203- !descriptor.collation ().isEmpty ();
204- if (!queryHasNaturalHint && isSpecialIndex) {
205- uasserted (ErrorCodes::InternalErrorNotSupported, " Unsupported index type" );
206- }
207-
208- // We do not want to try to build index metadata for a special index (since we do not
209- // support those yet in CQF) but we should allow the query to go through CQF if there is a
210- // $natural hint.
211- if (queryHasNaturalHint && isSpecialIndex) {
204+ !descriptor.collation ().isEmpty ()) {
205+ uassert (
206+ ErrorCodes::InternalErrorNotSupported, " Unsupported index type" , hasNaturalHint);
212207 continue ;
213208 }
214209
215210 if (indexHint) {
216211 if (indexHintName.empty ()) {
217- if (!SimpleBSONObjComparator::kInstance .evaluate (descriptor.keyPattern () ==
218- *indexHint)) {
219- // Index key pattern does not match hint.
220- skipIndex = true ;
221- }
222- } else if (indexHintName != descriptor.indexName ()) {
223- // Index name does not match hint.
224- skipIndex = true ;
212+ // Index hint is a key pattern. Check if it matches this descriptor's key pattern.
213+ skipIndex = SimpleBSONObjComparator::kInstance .evaluate (descriptor.keyPattern () !=
214+ *indexHint);
215+ } else {
216+ // Index hint is an index name. Check if it matches the descriptor's name.
217+ skipIndex = indexHintName != descriptor.indexName ();
225218 }
226219 }
227220
@@ -331,7 +324,7 @@ static std::pair<IndexDefinitions, MultikeynessTrie> buildIndexSpecsOptimizer(
331324 }
332325 }
333326 // For now we assume distribution is Centralized.
334- if (!skipIndex && !skipAllIndexes ) {
327+ if (!skipIndex && !hasNaturalHint ) {
335328 result.first .emplace (descriptor.indexName (), std::move (indexDef));
336329 }
337330 }
@@ -864,7 +857,10 @@ boost::optional<ExecParams> getSBEExecutorViaCascadesOptimizer(
864857
865858 const auto & collection = collections.getMainCollection ();
866859
867- validateCommandOptions (canonicalQuery, collection, indexHint, involvedCollections);
860+ const boost::optional<BSONObj>& hint =
861+ (indexHint && !indexHint->isEmpty () ? indexHint : boost::none);
862+
863+ validateCommandOptions (canonicalQuery, collection, hint, involvedCollections);
868864
869865 const bool requireRID = canonicalQuery ? canonicalQuery->getForceGenerateRecordId () : false ;
870866 const bool collectionExists = static_cast <bool >(collection);
@@ -882,7 +878,7 @@ boost::optional<ExecParams> getSBEExecutorViaCascadesOptimizer(
882878 collection,
883879 involvedCollections,
884880 nss,
885- indexHint ,
881+ hint ,
886882 scanProjName,
887883 uuidStr,
888884 scanDefName,
0 commit comments