From 8fb1d8039361bcbf3a0ab77127cc6712783485ca Mon Sep 17 00:00:00 2001 From: samontea Date: Tue, 16 Nov 2021 14:54:47 +0000 Subject: SERVER-60672 Simpler pushdown when timeseries collection has no mixed-schema buckets --- src/mongo/db/views/SConscript | 1 + src/mongo/db/views/resolved_view.cpp | 32 +++++++++++++++++++++++++++++++- src/mongo/db/views/resolved_view.h | 9 +++++++-- src/mongo/db/views/view_catalog.cpp | 18 +++++++++++++++++- 4 files changed, 56 insertions(+), 4 deletions(-) (limited to 'src/mongo/db/views') diff --git a/src/mongo/db/views/SConscript b/src/mongo/db/views/SConscript index 5ca16d561ed..38d2204fce9 100644 --- a/src/mongo/db/views/SConscript +++ b/src/mongo/db/views/SConscript @@ -27,6 +27,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/catalog/collection', '$BUILD_DIR/mongo/db/pipeline/aggregation', '$BUILD_DIR/mongo/db/query/collation/collator_factory_interface', '$BUILD_DIR/mongo/db/repl/repl_coordinator_interface', diff --git a/src/mongo/db/views/resolved_view.cpp b/src/mongo/db/views/resolved_view.cpp index 9c754c559e7..c0435b8e924 100644 --- a/src/mongo/db/views/resolved_view.cpp +++ b/src/mongo/db/views/resolved_view.cpp @@ -72,15 +72,30 @@ ResolvedView ResolvedView::fromBSON(const BSONObj& commandResponseObj) { collationSpec = collationElt.embeddedObject().getOwned(); } + + boost::optional mixedSchema = boost::none; + if (auto mixedSchemaElem = viewDef[kTimeseriesMayContainMixedData]) { + uassert(6067204, + str::stream() << "view definition must have " << kTimeseriesMayContainMixedData + << " of type bool or no such field", + mixedSchemaElem.type() == BSONType::Bool); + + mixedSchema = boost::optional(mixedSchemaElem.boolean()); + } + return {NamespaceString(viewDef["ns"].valueStringData()), std::move(pipeline), - std::move(collationSpec)}; + std::move(collationSpec), + std::move(mixedSchema)}; } void ResolvedView::serialize(BSONObjBuilder* builder) const { BSONObjBuilder subObj(builder->subobjStart("resolvedView")); subObj.append("ns", _namespace.ns()); subObj.append("pipeline", _pipeline); + // Only serialize if it doesn't contain mixed data. + if ((_timeseriesMayContainMixedData && !(*_timeseriesMayContainMixedData))) + subObj.append(kTimeseriesMayContainMixedData, *_timeseriesMayContainMixedData); if (!_defaultCollation.isEmpty()) { subObj.append("collation", _defaultCollation); } @@ -125,6 +140,21 @@ AggregateCommandRequest ResolvedView::asExpandedViewAggregation( } resolvedPipeline[1] = BSON(DocumentSourceInternalConvertBucketIndexStats::kStageName << builder.obj()); + } else if (resolvedPipeline.size() >= 1 && + resolvedPipeline[0][DocumentSourceInternalUnpackBucket::kStageNameInternal] && + serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo( + multiversion::FeatureCompatibilityVersion::kVersion_5_2)) { + auto unpackStage = resolvedPipeline[0]; + + BSONObjBuilder builder; + for (const auto& elem : + unpackStage[DocumentSourceInternalUnpackBucket::kStageNameInternal].Obj()) { + builder.append(elem); + } + builder.append(DocumentSourceInternalUnpackBucket::kAssumeNoMixedSchemaData, + ((_timeseriesMayContainMixedData && !(*_timeseriesMayContainMixedData)))); + resolvedPipeline[0] = + BSON(DocumentSourceInternalUnpackBucket::kStageNameInternal << builder.obj()); } AggregateCommandRequest expandedRequest{_namespace, resolvedPipeline}; diff --git a/src/mongo/db/views/resolved_view.h b/src/mongo/db/views/resolved_view.h index 19cfefe82f9..d19642c8dd5 100644 --- a/src/mongo/db/views/resolved_view.h +++ b/src/mongo/db/views/resolved_view.h @@ -46,10 +46,12 @@ class ResolvedView final : public ErrorExtraInfo { public: ResolvedView(const NamespaceString& collectionNs, std::vector pipeline, - BSONObj defaultCollation) + BSONObj defaultCollation, + boost::optional timeseriesMayContainMixedData = boost::none) : _namespace(collectionNs), _pipeline(std::move(pipeline)), - _defaultCollation(std::move(defaultCollation)) {} + _defaultCollation(std::move(defaultCollation)), + _timeseriesMayContainMixedData(timeseriesMayContainMixedData) {} static ResolvedView fromBSON(const BSONObj& commandResponseObj); @@ -74,6 +76,7 @@ public: // ErrorExtraInfo API static constexpr auto code = ErrorCodes::CommandOnShardedViewNotSupportedOnMongod; + static constexpr StringData kTimeseriesMayContainMixedData = "timeseriesMayContainMixedData"_sd; void serialize(BSONObjBuilder* bob) const final; static std::shared_ptr parse(const BSONObj&); @@ -88,6 +91,8 @@ private: // that operations on the view which do not specify a collation inherit the default. Operations // on the view which specify any other collation fail with a user error. BSONObj _defaultCollation; + + boost::optional _timeseriesMayContainMixedData; }; } // namespace mongo diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp index 84e0f7b46a8..b043eb5a03d 100644 --- a/src/mongo/db/views/view_catalog.cpp +++ b/src/mongo/db/views/view_catalog.cpp @@ -740,6 +740,7 @@ StatusWith ViewCatalog::resolveView( std::vector dependencyChain{nss}; int depth = 0; + boost::optional mixedData = boost::none; for (; depth < ViewGraph::kMaxViewDepth; depth++) { auto view = _lookup(opCtx, *resolvedNss, ViewCatalogLookupBehavior::kValidateDurableViews); @@ -761,10 +762,25 @@ StatusWith ViewCatalog::resolveView( return StatusWith( {*resolvedNss, std::move(resolvedPipeline), - collation ? std::move(collation.get()) : CollationSpec::kSimpleSpec}); + collation ? std::move(collation.get()) : CollationSpec::kSimpleSpec, + mixedData}); } resolvedNss = &view->viewOn(); + + if (view->timeseries()) { + auto tsCollection = + CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, *resolvedNss); + tassert(6067201, + str::stream() << "expected time-series buckets collection " << *resolvedNss + << " to exist", + + tsCollection); + mixedData = tsCollection + ? tsCollection->getTimeseriesBucketsMayHaveMixedSchemaData() + : false; + } + dependencyChain.push_back(*resolvedNss); if (!collation) { if (timeSeriesCollator) { -- cgit v1.2.1