diff --git a/src/mongo/db/commands/query_cmd/find_cmd.cpp b/src/mongo/db/commands/query_cmd/find_cmd.cpp index 1d433838284..6b7d4d29db7 100644 --- a/src/mongo/db/commands/query_cmd/find_cmd.cpp +++ b/src/mongo/db/commands/query_cmd/find_cmd.cpp @@ -73,6 +73,7 @@ #include "mongo/db/query/client_cursor/cursor_response.h" #include "mongo/db/query/collation/collator_factory_interface.h" #include "mongo/db/query/collation/collator_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/compiler/parsers/matcher/expression_parser.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/explain_diagnostic_printer.h" @@ -188,10 +189,13 @@ std::unique_ptr parseQueryAndBeginOperation( const auto& collection = collOrViewAcquisition.getCollectionPtr(); const auto* collator = collection ? collection->getDefaultCollator() : nullptr; - auto expCtx = ExpressionContextBuilder{} - .fromRequest(opCtx, *findCommand, collator, allowDiskUseByDefault.load()) - .tmpDir(boost::filesystem::path(storageGlobalParams.dbpath) / "_tmp") - .build(); + auto expCtx = + ExpressionContextBuilder{} + .fromRequest(opCtx, *findCommand, collator, allowDiskUseByDefault.load()) + .tmpDir(boost::filesystem::path(storageGlobalParams.dbpath) / "_tmp") + .mainCollPathArrayness( + collection ? CollectionQueryInfo::get(collection).getPathArrayness() : nullptr) + .build(); expCtx->startExpressionCounters(); auto parsedRequest = uassertStatusOK(parsed_find_command::parse( expCtx, @@ -521,6 +525,9 @@ public: .fromRequest(opCtx, *_cmdRequest, collator, allowDiskUseByDefault.load()) .explain(verbosity) .tmpDir(boost::filesystem::path(storageGlobalParams.dbpath) / "_tmp") + .mainCollPathArrayness( + collectionPtr ? CollectionQueryInfo::get(collectionPtr).getPathArrayness() + : nullptr) .build(); expCtx->startExpressionCounters(); diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index beb15e7f6aa..e46c0c98164 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -48,6 +48,7 @@ #include "mongo/db/pipeline/variables.h" #include "mongo/db/query/collation/collation_spec.h" #include "mongo/db/query/collation/collator_interface.h" +#include "mongo/db/query/compiler/metadata/path_arrayness.h" #include "mongo/db/query/datetime/date_time_support.h" #include "mongo/db/query/explain_options.h" #include "mongo/db/query/query_feature_flags_gen.h" @@ -1019,6 +1020,17 @@ public: return _featureFlagMqlJsEngineGap.get(VersionContext::getDecoration(getOperationContext())); } + const PathArrayness& getMainCollPathArrayness() const { + // mainCollPathArrayness will be unset in cases where we do not do a collection acquisition, + // e.g. if running on a 'mongos'. In this case, we return an empty instance of + // 'PathArrayness' that denotes all paths as arrays. + if (!_params.mainCollPathArrayness) { + static const auto kEmptyPathArrayness = PathArrayness(); + return kEmptyPathArrayness; + } + return *_params.mainCollPathArrayness; + } + protected: struct ExpressionContextParams { OperationContext* opCtx = nullptr; @@ -1160,6 +1172,10 @@ protected: // Indicates that the query is replanned after being rate-limited. bool wasRateLimited = false; + + // The PathArrayness information for the main collection. This may remain unset if a + // collection acquisition is not possible, e.g. when running on mongos. + std::shared_ptr mainCollPathArrayness = nullptr; }; ExpressionContextParams _params; diff --git a/src/mongo/db/pipeline/expression_context_builder.cpp b/src/mongo/db/pipeline/expression_context_builder.cpp index 5a0266c00c9..0c34220feff 100644 --- a/src/mongo/db/pipeline/expression_context_builder.cpp +++ b/src/mongo/db/pipeline/expression_context_builder.cpp @@ -392,6 +392,12 @@ ExpressionContextBuilder& ExpressionContextBuilder::tailableMode(TailableModeEnu return *this; } +ExpressionContextBuilder& ExpressionContextBuilder::mainCollPathArrayness( + std::shared_ptr mainCollPathArrayness) { + params.mainCollPathArrayness = mainCollPathArrayness; + return *this; +} + ExpressionContextBuilder& ExpressionContextBuilder::fromRequest( OperationContext* operationContext, const FindCommandRequest& request, diff --git a/src/mongo/db/pipeline/expression_context_builder.h b/src/mongo/db/pipeline/expression_context_builder.h index 83dd0cefabc..535ca009bdf 100644 --- a/src/mongo/db/pipeline/expression_context_builder.h +++ b/src/mongo/db/pipeline/expression_context_builder.h @@ -105,6 +105,8 @@ public: boost::optional>>); ExpressionContextBuilder& originalNs(NamespaceString); ExpressionContextBuilder& isHybridSearch(bool); + ExpressionContextBuilder& mainCollPathArrayness( + std::shared_ptr mainCollPathArrayness); /** * Add kSessionTransactionsTableNamespace, and kRsOplogNamespace diff --git a/src/mongo/db/query/compiler/metadata/path_arrayness.cpp b/src/mongo/db/query/compiler/metadata/path_arrayness.cpp index 696d12844c3..4b068b01fd7 100644 --- a/src/mongo/db/query/compiler/metadata/path_arrayness.cpp +++ b/src/mongo/db/query/compiler/metadata/path_arrayness.cpp @@ -29,6 +29,8 @@ #include "mongo/db/query/compiler/metadata/path_arrayness.h" +#include "mongo/logv2/log.h" + #include using namespace mongo::multikey_paths; @@ -126,10 +128,4 @@ void PathArrayness::TrieNode::insertPath(const FieldPath& path, // Recursively invoke the remaining path. _children.at(fieldNameToInsert).insertPath(path, multikeyPath, ++depth); } - -PathArrayness build(std::vector entries) { - PathArrayness root; - return root; -} - } // namespace mongo diff --git a/src/mongo/db/query/compiler/metadata/path_arrayness.h b/src/mongo/db/query/compiler/metadata/path_arrayness.h index a97db3664a5..ece8bc2dad5 100644 --- a/src/mongo/db/query/compiler/metadata/path_arrayness.h +++ b/src/mongo/db/query/compiler/metadata/path_arrayness.h @@ -29,8 +29,8 @@ #pragma once +#include "mongo/db/index/multikey_paths.h" #include "mongo/db/pipeline/field_path.h" -#include "mongo/db/query/compiler/metadata/index_entry.h" #include "mongo/util/modules.h" namespace mongo { @@ -140,10 +140,4 @@ private: */ TrieNode _root; }; - -/** - * Build an arrayness trie from a given vector of index entries. - */ -PathArrayness build(std::vector entries); - } // namespace mongo