summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2021-08-04 13:02:37 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-08-04 13:24:20 +0000
commitd0eb0b5775e46895ab5e884db2af70632615c70e (patch)
tree0c9e5566a7cb261543d367ab64c8ca6d0994bc66
parentd644971af8d2315cadf23b2c7addd7fe05ea3c2d (diff)
downloadmongo-d0eb0b5775e46895ab5e884db2af70632615c70e.tar.gz
SERVER-58061 Support compound indexes on time-series metadata and measurements
-rw-r--r--jstests/core/timeseries/timeseries_metric_index_compound.js169
1 files changed, 169 insertions, 0 deletions
diff --git a/jstests/core/timeseries/timeseries_metric_index_compound.js b/jstests/core/timeseries/timeseries_metric_index_compound.js
new file mode 100644
index 00000000000..44464704e27
--- /dev/null
+++ b/jstests/core/timeseries/timeseries_metric_index_compound.js
@@ -0,0 +1,169 @@
+/**
+ * Tests creating and using compound indexes on time-series metadata and measurement fields.
+ *
+ * @tags: [
+ * assumes_no_implicit_collection_creation_after_drop,
+ * does_not_support_stepdowns,
+ * does_not_support_transactions,
+ * requires_fcv_51,
+ * requires_find_command,
+ * requires_getmore,
+ * ]
+ */
+(function() {
+"use strict";
+
+load("jstests/core/timeseries/libs/timeseries.js");
+
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
+ jsTestLog(
+ "Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
+ return;
+}
+
+TimeseriesTest.run((insert) => {
+ const collName = "timeseries_metric_index_compound";
+
+ const timeFieldName = "tm";
+ const metaFieldName = "mm";
+
+ // Unique metadata values to create separate buckets.
+ const docs = [
+ {
+ _id: 0,
+ [timeFieldName]: ISODate(),
+ [metaFieldName]: {tag: "a", r: 1, loc: {type: "Point", coordinates: [3, 3]}},
+ x: 1,
+ z: true
+ },
+ {
+ _id: 1,
+ [timeFieldName]: ISODate(),
+ [metaFieldName]: {tag: "b", r: {s: true}, loc: [3, 3]},
+ x: 2,
+ z: false
+ },
+ {
+ _id: 2,
+ [timeFieldName]: ISODate(),
+ [metaFieldName]: {tag: "c", "r.s": "val", loc: {type: "Point", coordinates: [3, 2]}},
+ "x.y": 3,
+ z: true
+ },
+ {
+ _id: 3,
+ [timeFieldName]: ISODate(),
+ [metaFieldName]: {tag: "d", r: "val", loc: [1, 0]},
+ x: {y: 4},
+ z: false
+ }
+ ];
+
+ const setup = function(keysForCreate) {
+ const coll = db.getCollection(collName);
+ coll.drop();
+
+ jsTestLog("Setting up collection: " + coll.getFullName() +
+ " with index: " + tojson(keysForCreate));
+
+ assert.commandWorked(db.createCollection(
+ coll.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
+
+ // Insert data on the time-series collection and index it.
+ assert.commandWorked(insert(coll, docs), "failed to insert docs: " + tojson(docs));
+ assert.commandWorked(coll.createIndex(keysForCreate),
+ "failed to create index: " + tojson(keysForCreate));
+ };
+
+ const testHint = function(indexName) {
+ const coll = db.getCollection(collName);
+ const bucketsColl = db.getCollection("system.buckets." + collName);
+
+ // Tests hint() using the index name.
+ assert.eq(docs.length, bucketsColl.find().hint(indexName).toArray().length);
+ assert.eq(docs.length, coll.find().hint(indexName).toArray().length);
+
+ // Tests that hint() cannot be used when the index is hidden.
+ assert.commandWorked(coll.hideIndex(indexName));
+ assert.commandFailedWithCode(
+ assert.throws(() => bucketsColl.find().hint(indexName).toArray()), ErrorCodes.BadValue);
+ assert.commandFailedWithCode(assert.throws(() => coll.find().hint(indexName).toArray()),
+ ErrorCodes.BadValue);
+ assert.commandWorked(coll.unhideIndex(indexName));
+ };
+
+ const testIndex = function(viewDefinition, bucketsDefinition) {
+ const coll = db.getCollection(collName);
+ const bucketsColl = db.getCollection("system.buckets." + collName);
+
+ setup(viewDefinition);
+
+ // Check definition on view
+ let userIndexes = coll.getIndexes();
+ assert.eq(1, userIndexes.length);
+ assert.eq(viewDefinition, userIndexes[0].key);
+
+ // Check definition on buckets collection
+ let bucketIndexes = bucketsColl.getIndexes();
+ assert.eq(1, bucketIndexes.length);
+ assert.eq(bucketsDefinition, bucketIndexes[0].key);
+
+ testHint(bucketIndexes[0].name);
+
+ // Drop index by key pattern.
+ assert.commandWorked(coll.dropIndex(viewDefinition));
+ bucketIndexes = bucketsColl.getIndexes();
+ assert.eq(0, bucketIndexes.length);
+ };
+
+ // Test metadata-only indexes.
+ testIndex({[`${metaFieldName}.tag`]: 1, [`${metaFieldName}.r`]: 1},
+ {"meta.tag": 1, "meta.r": 1});
+ testIndex({[`${metaFieldName}.tag`]: 1, [`${metaFieldName}.loc`]: "2dsphere"},
+ {"meta.tag": 1, "meta.loc": "2dsphere"});
+ testIndex({[`${metaFieldName}.loc`]: "2dsphere", [`${metaFieldName}.tag`]: 1},
+ {"meta.loc": "2dsphere", "meta.tag": 1});
+
+ // Test measurement-only indexes.
+ testIndex({x: 1, z: 1},
+ {"control.max.x": 1, "control.min.x": 1, "control.max.z": 1, "control.min.z": 1});
+ testIndex({x: -1, z: -1},
+ {"control.min.x": -1, "control.max.x": -1, "control.min.z": -1, "control.max.z": -1});
+ testIndex({x: 1, z: -1},
+ {"control.max.x": 1, "control.min.x": 1, "control.min.z": -1, "control.max.z": -1});
+ testIndex({x: -1, z: 1},
+ {"control.min.x": -1, "control.max.x": -1, "control.max.z": 1, "control.min.z": 1});
+
+ // Test mixed metadata and measurement indexes.
+ testIndex({[`${metaFieldName}.r.s`]: 1, x: 1},
+ {"meta.r.s": 1, "control.max.x": 1, "control.min.x": 1});
+ testIndex({[`${metaFieldName}.r.s`]: 1, x: -1},
+ {"meta.r.s": 1, "control.min.x": -1, "control.max.x": -1});
+ testIndex({x: 1, [`${metaFieldName}.r.s`]: 1},
+ {"control.max.x": 1, "control.min.x": 1, "meta.r.s": 1});
+ testIndex({x: -1, [`${metaFieldName}.r.s`]: 1},
+ {"control.min.x": -1, "control.max.x": -1, "meta.r.s": 1});
+ testIndex({x: 1, [`${metaFieldName}.loc`]: "2dsphere", z: -1}, {
+ "control.max.x": 1,
+ "control.min.x": 1,
+ "meta.loc": "2dsphere",
+ "control.min.z": -1,
+ "control.max.z": -1
+ });
+
+ // Test bad input.
+ const testBadIndex = function(keysForCreate) {
+ const coll = db.getCollection(collName);
+ coll.drop();
+
+ assert.commandWorked(db.createCollection(
+ coll.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
+
+ assert.commandFailedWithCode(coll.createIndex(keysForCreate), ErrorCodes.CannotCreateIndex);
+ };
+
+ testBadIndex({x: 1, z: "abc"});
+ testBadIndex({x: 1, z: {y: 1}});
+ testBadIndex({x: true, z: 1});
+});
+}());