summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2021-11-05 15:47:37 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-11-05 16:34:50 +0000
commit205bcaa9c722e425e7ca45acf89956841bfcf8da (patch)
tree252229bf327a17961871cbf69c9c3feab4fc21a0
parent7bcb659c013aaf44e1edab7b8a102a738c0bfb8c (diff)
downloadmongo-205bcaa9c722e425e7ca45acf89956841bfcf8da.tar.gz
SERVER-61175 Store the original user index definition on the transformed index definition on the buckets collection for partial indexes
-rw-r--r--jstests/core/timeseries/timeseries_index.js13
-rw-r--r--jstests/core/timeseries/timeseries_index_spec.js70
-rw-r--r--jstests/noPassthrough/timeseries_measurement_indexes_downgrade.js31
-rw-r--r--src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp20
-rw-r--r--src/mongo/db/timeseries/timeseries_constants.h1
-rw-r--r--src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.cpp5
6 files changed, 104 insertions, 36 deletions
diff --git a/jstests/core/timeseries/timeseries_index.js b/jstests/core/timeseries/timeseries_index.js
index 0a6bbd6d51a..6cddbdc2ea8 100644
--- a/jstests/core/timeseries/timeseries_index.js
+++ b/jstests/core/timeseries/timeseries_index.js
@@ -4,7 +4,7 @@
* @tags: [
* does_not_support_stepdowns,
* does_not_support_transactions,
- * requires_fcv_51,
+ * requires_fcv_52,
* requires_getmore,
* ]
*/
@@ -275,10 +275,13 @@ TimeseriesTest.run((insert) => {
[ErrorCodes.CannotCreateIndex, ErrorCodes.InvalidOptions]);
};
- // Partial indexes are not supported on time-series collections.
- testCreateIndexFailed({[metaFieldName]: 1}, {partialFilterExpression: {meta: {$gt: 5}}});
- testCreateIndexFailed({[metaFieldName]: 1},
- {partialFilterExpression: {[metaFieldName]: {$gt: 5}}});
+ if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
+ // Partial indexes are not supported on time-series collections if the time-series metric
+ // feature flag is disabled.
+ testCreateIndexFailed({[metaFieldName]: 1}, {partialFilterExpression: {meta: {$gt: 5}}});
+ testCreateIndexFailed({[metaFieldName]: 1},
+ {partialFilterExpression: {[metaFieldName]: {$gt: 5}}});
+ }
// Unique indexes are not supported on clustered collections.
testCreateIndexFailed({[metaFieldName]: 1}, {unique: true});
diff --git a/jstests/core/timeseries/timeseries_index_spec.js b/jstests/core/timeseries/timeseries_index_spec.js
index c27354be313..eaf7065d3e9 100644
--- a/jstests/core/timeseries/timeseries_index_spec.js
+++ b/jstests/core/timeseries/timeseries_index_spec.js
@@ -30,48 +30,68 @@ TimeseriesTest.run(() => {
assert.commandWorked(db.createCollection(
coll.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
- assert.commandWorked(coll.createIndex({[timeFieldName]: 1}));
- assert.commandWorked(coll.createIndex({[metaFieldName]: 1}));
-
- if (TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
- assert.commandWorked(coll.createIndex({x: 1}, {name: "x"}));
- }
-
- const checkIndexSpec = function(spec, userIndex) {
+ const checkIndexSpec = function(spec, userIndex, isDowngradeCompatible) {
assert(spec.hasOwnProperty("v"));
assert(spec.hasOwnProperty("name"));
assert(spec.hasOwnProperty("key"));
if (userIndex) {
assert(!spec.hasOwnProperty("originalSpec"));
-
- if (spec.name == "x") {
- assert.eq(spec.key, {x: 1});
- }
-
return;
}
- if (spec.name == "x") {
+ if (!isDowngradeCompatible) {
assert(spec.hasOwnProperty("originalSpec"));
assert.eq(spec.v, spec.originalSpec.v);
assert.eq(spec.name, spec.originalSpec.name);
assert.neq(spec.key, spec.originalSpec.key);
-
- assert.eq(spec.key, {"control.min.x": 1, "control.max.x": 1});
} else {
assert(!spec.hasOwnProperty("originalSpec"));
}
};
- let userIndexes = coll.getIndexes();
- for (const index of userIndexes) {
- checkIndexSpec(index, /*userIndex=*/true);
- }
+ const verifyAndDropIndex = function(isDowngradeCompatible) {
+ let userIndexes = coll.getIndexes();
+ for (const index of userIndexes) {
+ checkIndexSpec(index, /*userIndex=*/true, isDowngradeCompatible);
+ }
+
+ let bucketIndexes = bucketsColl.getIndexes();
+ for (const index of bucketIndexes) {
+ checkIndexSpec(index, /*userIndex=*/false, isDowngradeCompatible);
+ }
+
+ assert.commandWorked(coll.dropIndexes("*"));
+ };
+
+ assert.commandWorked(coll.createIndex({[timeFieldName]: 1}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/true);
+
+ assert.commandWorked(coll.createIndex({[metaFieldName]: 1}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/true);
+
+ assert.commandWorked(coll.createIndex({[timeFieldName]: 1, [metaFieldName]: 1}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/true);
+
+ if (TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
+ assert.commandWorked(coll.createIndex({x: 1}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/false);
+
+ assert.commandWorked(
+ coll.createIndex({x: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/false);
+
+ assert.commandWorked(coll.createIndex({[timeFieldName]: 1},
+ {partialFilterExpression: {x: {$type: "number"}}}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/false);
+
+ assert.commandWorked(coll.createIndex({[metaFieldName]: 1},
+ {partialFilterExpression: {x: {$type: "number"}}}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/false);
- let bucketIndexes = bucketsColl.getIndexes();
- for (const index of bucketIndexes) {
- checkIndexSpec(index, /*userIndex=*/false);
+ assert.commandWorked(coll.createIndex({[metaFieldName]: 1, x: 1},
+ {partialFilterExpression: {x: {$type: "number"}}}));
+ verifyAndDropIndex(/*isDowngradeCompatible=*/false);
}
// Creating an index directly on the buckets collection is permitted. However, these types of
@@ -82,7 +102,7 @@ TimeseriesTest.run(() => {
bucketsColl.createIndex({"control.min.y": 1, "control.max.y": 1}, {name: "y"}));
let foundIndex = false;
- bucketIndexes = bucketsColl.getIndexes();
+ let bucketIndexes = bucketsColl.getIndexes();
for (const index of bucketIndexes) {
if (index.name == "y") {
foundIndex = true;
@@ -94,7 +114,7 @@ TimeseriesTest.run(() => {
// Verify that the bucket index can map to a user index.
foundIndex = false;
- userIndexes = coll.getIndexes();
+ let userIndexes = coll.getIndexes();
for (const index of userIndexes) {
if (index.name == "y") {
foundIndex = true;
diff --git a/jstests/noPassthrough/timeseries_measurement_indexes_downgrade.js b/jstests/noPassthrough/timeseries_measurement_indexes_downgrade.js
index 9a8593550d2..d1b913832a2 100644
--- a/jstests/noPassthrough/timeseries_measurement_indexes_downgrade.js
+++ b/jstests/noPassthrough/timeseries_measurement_indexes_downgrade.js
@@ -114,5 +114,36 @@ checkIndexForDowngrade(lastLTSFCV, true, false);
assert.commandWorked(coll.createIndex({[metaFieldName]: "2dsphere"}));
checkIndexForDowngrade(lastContinuousFCV, true, false);
+// Partial indexes are not supported in versions earlier than v5.2.
+assert.commandWorked(
+ coll.createIndex({[timeFieldName]: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastLTSFCV, false, false);
+
+assert.commandWorked(
+ coll.createIndex({[timeFieldName]: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastContinuousFCV, false, false);
+
+assert.commandWorked(
+ coll.createIndex({[metaFieldName]: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastLTSFCV, false, false);
+
+assert.commandWorked(
+ coll.createIndex({[metaFieldName]: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastContinuousFCV, false, false);
+
+assert.commandWorked(coll.createIndex({x: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastLTSFCV, false, false);
+
+assert.commandWorked(coll.createIndex({x: 1}, {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastContinuousFCV, false, false);
+
+assert.commandWorked(coll.createIndex({[metaFieldName]: 1, x: 1},
+ {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastLTSFCV, false, false);
+
+assert.commandWorked(coll.createIndex({x: 1, [metaFieldName]: 1},
+ {partialFilterExpression: {x: {$type: "number"}}}));
+checkIndexForDowngrade(lastContinuousFCV, false, false);
+
MongoRunner.stopMongod(conn);
}());
diff --git a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp
index db4e0295c61..e857ab8a3a8 100644
--- a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp
+++ b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp
@@ -78,11 +78,17 @@ CreateIndexesCommand makeTimeseriesCreateIndexesCommand(OperationContext* opCtx,
std::vector<mongo::BSONObj> indexes;
for (const auto& origIndex : origIndexes) {
BSONObjBuilder builder;
- bool isBucketsIndexSpecCompatibleForDowngrade = false;
+ bool isBucketsIndexSpecCompatibleForDowngrade = true;
for (const auto& elem : origIndex) {
if (elem.fieldNameStringData() == IndexDescriptor::kPartialFilterExprFieldName) {
- uasserted(ErrorCodes::InvalidOptions,
- "Partial indexes are not supported on time-series collections");
+ if (feature_flags::gTimeseriesMetricIndexes.isEnabledAndIgnoreFCV() &&
+ serverGlobalParams.featureCompatibility.isFCVUpgradingToOrAlreadyLatest()) {
+ // Partial indexes are not supported in FCV < 5.2.
+ isBucketsIndexSpecCompatibleForDowngrade = false;
+ } else {
+ uasserted(ErrorCodes::InvalidOptions,
+ "Partial indexes are not supported on time-series collections");
+ }
}
if (elem.fieldNameStringData() == IndexDescriptor::kSparseFieldName) {
@@ -132,10 +138,12 @@ CreateIndexesCommand makeTimeseriesCreateIndexesCommand(OperationContext* opCtx,
<< " Command request: " << redact(origCmd.toBSON({})),
bucketsIndexSpecWithStatus.isOK());
- isBucketsIndexSpecCompatibleForDowngrade =
- timeseries::isBucketsIndexSpecCompatibleForDowngrade(
+ if (!timeseries::isBucketsIndexSpecCompatibleForDowngrade(
options,
- BSON(NewIndexSpec::kKeyFieldName << bucketsIndexSpecWithStatus.getValue()));
+ BSON(NewIndexSpec::kKeyFieldName
+ << bucketsIndexSpecWithStatus.getValue()))) {
+ isBucketsIndexSpecCompatibleForDowngrade = false;
+ }
builder.append(NewIndexSpec::kKeyFieldName,
std::move(bucketsIndexSpecWithStatus.getValue()));
diff --git a/src/mongo/db/timeseries/timeseries_constants.h b/src/mongo/db/timeseries/timeseries_constants.h
index 24e69bc1837..28dfd25ce78 100644
--- a/src/mongo/db/timeseries/timeseries_constants.h
+++ b/src/mongo/db/timeseries/timeseries_constants.h
@@ -56,6 +56,7 @@ static constexpr StringData kMetaFieldName = "metaField"_sd;
// These are hard-coded field names in index specs.
static constexpr StringData kKeyFieldName = "key"_sd;
static constexpr StringData kOriginalSpecFieldName = "originalSpec"_sd;
+static constexpr StringData kPartialFilterExpressionFieldName = "partialFilterExpression"_sd;
static constexpr int kTimeseriesControlDefaultVersion = 1;
static constexpr int kTimeseriesControlCompressedVersion = 2;
diff --git a/src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.cpp b/src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.cpp
index 06b701a0f92..570ab781281 100644
--- a/src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.cpp
+++ b/src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.cpp
@@ -389,6 +389,11 @@ bool isBucketsIndexSpecCompatibleForDowngrade(const TimeseriesOptions& timeserie
return false;
}
+ if (bucketsIndex.hasField(kPartialFilterExpressionFieldName)) {
+ // Partial indexes are not supported in FCV < 5.2.
+ return false;
+ }
+
return createTimeseriesIndexSpecFromBucketsIndexSpec(
timeseriesOptions,
bucketsIndex.getField(kKeyFieldName).Obj(),