diff options
-rw-r--r-- | src/mongo/db/timeseries/bucket_catalog.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/timeseries/bucket_catalog_helpers.cpp | 41 | ||||
-rw-r--r-- | src/mongo/db/timeseries/bucket_catalog_helpers.h | 14 | ||||
-rw-r--r-- | src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp | 21 |
4 files changed, 74 insertions, 25 deletions
diff --git a/src/mongo/db/timeseries/bucket_catalog.cpp b/src/mongo/db/timeseries/bucket_catalog.cpp index cef4bb3a964..d7d07cb5c8c 100644 --- a/src/mongo/db/timeseries/bucket_catalog.cpp +++ b/src/mongo/db/timeseries/bucket_catalog.cpp @@ -1285,14 +1285,23 @@ StatusWith<std::pair<BucketCatalog::BucketKey, Date_t>> BucketCatalog::_extractB const StringData::ComparatorInterface* comparator, const TimeseriesOptions& options, const BSONObj& doc) const { - auto swDocTimeAndMeta = timeseries::extractTimeAndMeta(doc, options); - if (!swDocTimeAndMeta.isOK()) { - return swDocTimeAndMeta.getStatus(); - } - auto time = swDocTimeAndMeta.getValue().first; + Date_t time; BSONElement metadata; - if (auto metadataValue = swDocTimeAndMeta.getValue().second) { - metadata = *metadataValue; + + if (!options.getMetaField().has_value()) { + auto swTime = timeseries::extractTime(doc, options.getTimeField()); + if (!swTime.isOK()) { + return swTime.getStatus(); + } + time = swTime.getValue(); + } else { + auto swDocTimeAndMeta = timeseries::extractTimeAndMeta( + doc, options.getTimeField(), options.getMetaField().value()); + if (!swDocTimeAndMeta.isOK()) { + return swDocTimeAndMeta.getStatus(); + } + time = swDocTimeAndMeta.getValue().first; + metadata = swDocTimeAndMeta.getValue().second; } // Buckets are spread across independently-lockable stripes to improve parallelism. We map a diff --git a/src/mongo/db/timeseries/bucket_catalog_helpers.cpp b/src/mongo/db/timeseries/bucket_catalog_helpers.cpp index b54518eafb7..4500212e420 100644 --- a/src/mongo/db/timeseries/bucket_catalog_helpers.cpp +++ b/src/mongo/db/timeseries/bucket_catalog_helpers.cpp @@ -197,22 +197,45 @@ StatusWith<Schema> generateSchemaFromBucketDoc(const BSONObj& bucketDoc, } } -StatusWith<std::pair<Date_t, boost::optional<BSONElement>>> extractTimeAndMeta( - const BSONObj& doc, const TimeseriesOptions& options) { - auto timeElem = doc[options.getTimeField()]; +StatusWith<Date_t> extractTime(const BSONObj& doc, StringData timeFieldName) { + auto timeElem = doc[timeFieldName]; if (!timeElem || BSONType::Date != timeElem.type()) { return {ErrorCodes::BadValue, - str::stream() << "'" << options.getTimeField() << "' must be present and contain a " + str::stream() << "'" << timeFieldName << "' must be present and contain a " << "valid BSON UTC datetime value"}; } + return timeElem.Date(); +} - auto time = timeElem.Date(); - auto metaFieldName = options.getMetaField(); - if (metaFieldName) { - return std::make_pair(time, doc[*metaFieldName]); +StatusWith<std::pair<Date_t, BSONElement>> extractTimeAndMeta(const BSONObj& doc, + StringData timeFieldName, + StringData metaFieldName) { + // Iterate the document once, checking for both fields. + BSONElement timeElem; + BSONElement metaElem; + for (auto&& el : doc) { + if (!timeElem && el.fieldNameStringData() == timeFieldName) { + timeElem = el; + if (metaElem) { + break; + } + } else if (!metaElem && el.fieldNameStringData() == metaFieldName) { + metaElem = el; + if (timeElem) { + break; + } + } + } + + if (!timeElem || BSONType::Date != timeElem.type()) { + return {ErrorCodes::BadValue, + str::stream() << "'" << timeFieldName << "' must be present and contain a " + << "valid BSON UTC datetime value"}; } - return std::make_pair(time, boost::none); + auto time = timeElem.Date(); + + return std::make_pair(time, metaElem); } void normalizeMetadata(BSONObjBuilder* builder, diff --git a/src/mongo/db/timeseries/bucket_catalog_helpers.h b/src/mongo/db/timeseries/bucket_catalog_helpers.h index f81004ca147..aa00c9541da 100644 --- a/src/mongo/db/timeseries/bucket_catalog_helpers.h +++ b/src/mongo/db/timeseries/bucket_catalog_helpers.h @@ -57,12 +57,20 @@ StatusWith<Schema> generateSchemaFromBucketDoc(const BSONObj& bucketDoc, const StringData::ComparatorInterface* comparator); /** - * Extracts the time field of a measurement document and its meta field if it is present. + * Extracts the time field of a measurement document. * * Returns a bad status if the document is malformed. */ -StatusWith<std::pair<Date_t, boost::optional<BSONElement>>> extractTimeAndMeta( - const BSONObj& doc, const TimeseriesOptions& options); +StatusWith<Date_t> extractTime(const BSONObj& doc, StringData timeFieldName); + +/** + * Extracts the time field of a measurement document and its meta field. + * + * Returns a bad status if the document is malformed. + */ +StatusWith<std::pair<Date_t, BSONElement>> extractTimeAndMeta(const BSONObj& doc, + StringData timeFieldName, + StringData metaFieldName); /** diff --git a/src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp b/src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp index 150f6e0377f..0a5442d4080 100644 --- a/src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp +++ b/src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp @@ -76,18 +76,27 @@ BSONObj BucketCatalogHelpersTest::_findSuitableBucket(OperationContext* opCtx, "Missing bucketMaxSpanSeconds option.", options.getBucketMaxSpanSeconds()); - auto swDocTimeAndMeta = timeseries::extractTimeAndMeta(measurementDoc, options); - if (!swDocTimeAndMeta.isOK()) { - return BSONObj(); + Date_t time; + BSONElement metadata; + if (!options.getMetaField().has_value()) { + auto swTime = timeseries::extractTime(measurementDoc, options.getTimeField()); + ASSERT_OK(swTime); + time = swTime.getValue(); + } else { + auto swDocTimeAndMeta = timeseries::extractTimeAndMeta( + measurementDoc, options.getTimeField(), options.getMetaField().value()); + ASSERT_OK(swDocTimeAndMeta); + time = swDocTimeAndMeta.getValue().first; + metadata = swDocTimeAndMeta.getValue().second; } - auto [time, metadata] = swDocTimeAndMeta.getValue(); + auto controlMinTimePath = timeseries::kControlMinFieldNamePrefix.toString() + options.getTimeField(); boost::optional<BSONObj> normalizedMetadata; - if (metadata && (*metadata).ok()) { + if (metadata.ok()) { BSONObjBuilder builder; - timeseries::normalizeMetadata(&builder, *metadata, timeseries::kBucketMetaFieldName); + timeseries::normalizeMetadata(&builder, metadata, timeseries::kBucketMetaFieldName); normalizedMetadata = builder.obj(); } |