summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2022-12-01 22:21:19 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-12-06 15:47:15 +0000
commit9d78ef337bb3d87808775a631927f52ab126cf7f (patch)
treeb541cd3d12116593e92b0ddcd279be6097fea0b1
parent89b2e659a29e08418ea99989043cc7a32591d146 (diff)
downloadmongo-9d78ef337bb3d87808775a631927f52ab126cf7f.tar.gz
SERVER-71718 Refactor extractTimeAndMeta to branch earlier and iterate document once
(cherry picked from commit 88d18f93e89f1124fc121d4c8c10b936c851eb1a)
-rw-r--r--src/mongo/db/timeseries/bucket_catalog.cpp23
-rw-r--r--src/mongo/db/timeseries/bucket_catalog_helpers.cpp41
-rw-r--r--src/mongo/db/timeseries/bucket_catalog_helpers.h14
-rw-r--r--src/mongo/db/timeseries/bucket_catalog_helpers_test.cpp21
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();
}