diff options
author | Alyssa Wagenmaker <alyssa.wagenmaker@mongodb.com> | 2023-05-04 17:34:22 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-05-04 19:09:24 +0000 |
commit | 41d8e65dc85cf7a693fa3d46d7caf84b9dff802f (patch) | |
tree | 0d6cdf475ea7380e0502f4cea4757718d32d472f /jstests/core | |
parent | 4973d6f85a1a394aff14d4a2124ba993d666c604 (diff) | |
download | mongo-41d8e65dc85cf7a693fa3d46d7caf84b9dff802f.tar.gz |
SERVER-76625 Support basic modifier updates in TS_MODIFY
Diffstat (limited to 'jstests/core')
-rw-r--r-- | jstests/core/timeseries/timeseries_update.js | 48 | ||||
-rw-r--r-- | jstests/core/timeseries/timeseries_update_concurrent.js | 14 | ||||
-rw-r--r-- | jstests/core/timeseries/timeseries_update_multi.js | 603 |
3 files changed, 434 insertions, 231 deletions
diff --git a/jstests/core/timeseries/timeseries_update.js b/jstests/core/timeseries/timeseries_update.js index f71aa1524b2..bb91e83922c 100644 --- a/jstests/core/timeseries/timeseries_update.js +++ b/jstests/core/timeseries/timeseries_update.js @@ -352,17 +352,19 @@ TimeseriesTest.run((insert) => { }); // Rename the metaField. - testUpdate({ - initialDocList: [doc1, doc2, doc4], - updateList: [{ - q: {[metaFieldName + ".a"]: "A"}, - u: {$rename: {[metaFieldName]: "Z"}}, - multi: true, - }], - resultDocList: [doc1, doc2, doc4], - n: 0, - failCode: ErrorCodes.InvalidOptions, - }); + if (!arbitraryUpdatesEnabled) { + testUpdate({ + initialDocList: [doc1, doc2, doc4], + updateList: [{ + q: {[metaFieldName + ".a"]: "A"}, + u: {$rename: {[metaFieldName]: "Z"}}, + multi: true, + }], + resultDocList: [doc1, doc2, doc4], + n: 0, + failCode: ErrorCodes.InvalidOptions, + }); + } // Rename a subfield of the metaField. testUpdate({ @@ -378,17 +380,19 @@ TimeseriesTest.run((insert) => { }); // Rename a subfield of the metaField to something not in the metaField. - testUpdate({ - initialDocList: [doc1, doc2, doc4], - updateList: [{ - q: {[metaFieldName + ".a"]: "A"}, - u: {$rename: {[metaFieldName + ".a"]: "notMetaField.a"}}, - multi: true, - }], - resultDocList: [doc1, doc2, doc4], - n: 0, - failCode: ErrorCodes.InvalidOptions, - }); + if (!arbitraryUpdatesEnabled) { + testUpdate({ + initialDocList: [doc1, doc2, doc4], + updateList: [{ + q: {[metaFieldName + ".a"]: "A"}, + u: {$rename: {[metaFieldName + ".a"]: "notMetaField.a"}}, + multi: true, + }], + resultDocList: [doc1, doc2, doc4], + n: 0, + failCode: ErrorCodes.InvalidOptions, + }); + } // For all documents that have at least one 2 in its metaField array, update the first 2 // to be 100 using the positional $ operator. diff --git a/jstests/core/timeseries/timeseries_update_concurrent.js b/jstests/core/timeseries/timeseries_update_concurrent.js index c6a7b41aadf..7965e5dd65a 100644 --- a/jstests/core/timeseries/timeseries_update_concurrent.js +++ b/jstests/core/timeseries/timeseries_update_concurrent.js @@ -118,10 +118,12 @@ validateUpdateIndex( // Attempt to update a document in a collection that has been replaced with a new time-series // collection with a different metaField. -validateUpdateIndex( - docs, - [{q: {[metaFieldName]: {a: "B"}}, u: {$set: {[metaFieldName]: {c: "C"}}}, multi: true}], - testCases.REPLACE_METAFIELD, - ErrorCodes.InvalidOptions, - "meta"); +if (!TimeseriesTest.arbitraryUpdatesEnabled(db)) { + validateUpdateIndex( + docs, + [{q: {[metaFieldName]: {a: "B"}}, u: {$set: {[metaFieldName]: {c: "C"}}}, multi: true}], + testCases.REPLACE_METAFIELD, + ErrorCodes.InvalidOptions, + "meta"); +} })(); diff --git a/jstests/core/timeseries/timeseries_update_multi.js b/jstests/core/timeseries/timeseries_update_multi.js index 645e0d9ad4f..b586c0b093e 100644 --- a/jstests/core/timeseries/timeseries_update_multi.js +++ b/jstests/core/timeseries/timeseries_update_multi.js @@ -33,8 +33,8 @@ function testUpdate({ createCollectionWithMetaField = true, updateList, resultDocList, - n, - nModified = n, + nMatched, + nModified = nMatched, failCode, }) { const coll = testDB.getCollection(collNamePrefix + count++); @@ -50,7 +50,7 @@ function testUpdate({ const res = failCode ? assert.commandFailedWithCode(testDB.runCommand(updateCommand), failCode) : assert.commandWorked(testDB.runCommand(updateCommand)); - assert.eq(n, res.n); + assert.eq(nMatched, res.n); assert.eq(nModified, res.nModified); const resDocs = coll.find().toArray(); assert.eq(resDocs.length, resultDocList.length); @@ -63,257 +63,454 @@ function testUpdate({ }); } -const doc_a_b_no_metrics = { +const doc_id_1_a_b_no_metrics = { _id: 1, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", b: "B"}, }; -const doc_a_b_array_metric = { +const doc_id_2_a_b_array_metric = { _id: 2, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", b: "B"}, f: [{"k": "K", "v": "V"}], }; -const doc_a_b_string_metric = { +const doc_id_3_a_b_string_metric = { _id: 3, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", b: "B"}, f: "F", }; -const doc_no_meta_string_metric = { +const doc_id_4_no_meta_string_metric = { _id: 4, [timeFieldName]: dateTime, f: "F", }; -const doc_a_c_array_metric_1 = { +const doc_id_5_a_c_array_metric = { _id: 5, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", c: "C"}, f: [2, 3], }; -const doc_a_c_array_metric_2 = { +const doc_id_6_a_c_array_metric = { _id: 6, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", c: "C"}, f: [1, 10], }; -const doc_no_meta_int_metric = { +const doc_id_7_no_meta_int_metric = { _id: 7, [timeFieldName]: dateTime, g: 1, }; +const doc_id_8_array_meta = { + _id: 8, + [timeFieldName]: dateTime, + [metaFieldName]: [1, 2, 3, 4] +}; /** * Tests op-style updates */ // Query on the _id field and modify the metaField. -testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric], - updateList: [{ - q: {_id: {$lt: 10}}, - u: {$set: {[metaFieldName]: {c: "C"}}}, - multi: true, - }], - resultDocList: [ - {_id: 1, [timeFieldName]: dateTime, [metaFieldName]: {c: "C"}}, - { - _id: 2, - [timeFieldName]: dateTime, - [metaFieldName]: {c: "C"}, - f: [{"k": "K", "v": "V"}], - }, - ], - n: 2, -}); +(function testMetricFieldQueryMetaFieldUpdate() { + testUpdate({ + initialDocList: [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric], + updateList: [{ + q: {_id: {$lt: 10}}, + u: {$set: {[metaFieldName]: {c: "C"}}}, + multi: true, + }], + resultDocList: [ + {_id: 1, [timeFieldName]: dateTime, [metaFieldName]: {c: "C"}}, + { + _id: 2, + [timeFieldName]: dateTime, + [metaFieldName]: {c: "C"}, + f: [{"k": "K", "v": "V"}], + }, + ], + nMatched: 2, + }); +})(); + +// Query doesn't match any docs. +(function testZeroMeasurementUpdate() { + testUpdate({ + initialDocList: + [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric], + updateList: [{ + q: {someField: "doesNotExist"}, + u: {$set: {[metaFieldName]: {c: "C"}}}, + multi: true, + }], + resultDocList: + [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric], + nMatched: 0, + }); +})(); + +// No-op update. +(function testNoopUpdate() { + testUpdate({ + initialDocList: [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric], + updateList: [{ + q: {}, + u: {$set: {[metaFieldName]: {a: "A", b: "B"}}}, + multi: true, + }], + resultDocList: [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric], + nMatched: 2, + nModified: 0 + }); +})(); // Query on the metaField and modify the timeField. -testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric], - updateList: [{ - q: {[metaFieldName]: {a: "A", b: "B"}}, - u: {$set: {[timeFieldName]: dateTimeUpdated}}, - multi: true, - }], - resultDocList: [ - { - _id: 1, - [timeFieldName]: dateTimeUpdated, - [metaFieldName]: {a: "A", b: "B"}, - }, - { - _id: 2, - [timeFieldName]: dateTimeUpdated, - [metaFieldName]: {a: "A", b: "B"}, - f: [{"k": "K", "v": "V"}], - }, - ], - n: 2, -}); +(function testMetaFieldQueryTimeFieldUpdate() { + testUpdate({ + initialDocList: + [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric], + updateList: [{ + q: {[metaFieldName]: {a: "A", b: "B"}}, + u: {$set: {[timeFieldName]: dateTimeUpdated}}, + multi: true, + }], + resultDocList: [ + { + _id: 1, + [timeFieldName]: dateTimeUpdated, + [metaFieldName]: {a: "A", b: "B"}, + }, + { + _id: 2, + [timeFieldName]: dateTimeUpdated, + [metaFieldName]: {a: "A", b: "B"}, + f: [{"k": "K", "v": "V"}], + }, + doc_id_5_a_c_array_metric + ], + nMatched: 2, + }); +})(); -// Query on the metaField and a field that is not the metaField. -testUpdate({ - initialDocList: [doc_a_b_string_metric], - updateList: [{ - q: {[metaFieldName]: {a: "A", b: "B"}, f: "F"}, - u: {$set: {[metaFieldName]: {c: "C"}}}, - multi: true, - }], - resultDocList: [ - { - _id: 3, - [timeFieldName]: dateTime, - [metaFieldName]: {c: "C"}, - f: "F", - }, - ], - n: 1, -}); +// Query on the metaField and a metric field. +(function testMetaFieldQueryMetricFieldMetric() { + testUpdate({ + initialDocList: [doc_id_3_a_b_string_metric, doc_id_2_a_b_array_metric], + updateList: [{ + q: {[metaFieldName]: {a: "A", b: "B"}, f: "F"}, + u: {$set: {[metaFieldName]: {c: "C"}}}, + multi: true, + }], + resultDocList: [ + { + _id: 3, + [timeFieldName]: dateTime, + [metaFieldName]: {c: "C"}, + f: "F", + }, + doc_id_2_a_b_array_metric + ], + nMatched: 1, + }); +})(); -// Query on the metaField and modify the metaField and a field that is not the metaField. -testUpdate({ - initialDocList: [doc_a_b_string_metric], - updateList: [{ - q: {[metaFieldName]: {a: "A", b: "B"}}, - u: {$set: {[metaFieldName]: {c: "C"}, f: "FF"}}, - multi: true, - }], - resultDocList: [ - { - _id: 3, - [timeFieldName]: dateTime, - [metaFieldName]: {c: "C"}, - f: "FF", - }, - ], - n: 1, -}); +// Query on the metaField and modify the metaField and a metric field. +(function testMetaFieldQueryMetaAndMetricFieldUpdate() { + testUpdate({ + initialDocList: [doc_id_3_a_b_string_metric, doc_id_2_a_b_array_metric], + updateList: [{ + q: {[metaFieldName]: {a: "A", b: "B"}}, + u: {$set: {[metaFieldName]: {c: "C"}, f: "FF"}}, + multi: true, + }], + resultDocList: [ + { + _id: 3, + [timeFieldName]: dateTime, + [metaFieldName]: {c: "C"}, + f: "FF", + }, + { + _id: 2, + [timeFieldName]: dateTime, + [metaFieldName]: {c: "C"}, + f: "FF", + } + ], + nMatched: 2, + }); +})(); // This command will fail because all time-series collections require a time field. -testUpdate({ - initialDocList: [doc_a_b_string_metric, doc_a_c_array_metric_1], - updateList: [{ - q: {f: "F"}, - u: {$unset: {[timeFieldName]: ""}}, - multi: true, - }], - resultDocList: [ - doc_a_b_string_metric, - doc_a_c_array_metric_1, - ], - n: 0, - failCode: ErrorCodes.InvalidOptions, -}); +(function testRemoveTimeField() { + testUpdate({ + initialDocList: [doc_id_3_a_b_string_metric, doc_id_5_a_c_array_metric], + updateList: [{ + q: {f: "F"}, + u: {$unset: {[timeFieldName]: ""}}, + multi: true, + }], + resultDocList: [ + doc_id_3_a_b_string_metric, + doc_id_5_a_c_array_metric, + ], + nMatched: 0, + failCode: ErrorCodes.BadValue, + }); +})(); // Query on the time field and remove the metaField. -testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric, doc_a_c_array_metric_1], - updateList: [{ - q: {[timeField]: dateTime}, - u: {$unset: {[metaFieldName]: ""}, multi: true}, - multi: true, - }], - resultDocList: [ - { - _id: 1, - [timeFieldName]: dateTime, - }, - { - _id: 2, - [timeFieldName]: dateTime, - f: [{"k": "K", "v": "V"}], - }, - { - _id: 5, - [timeFieldName]: dateTime, - f: [2, 3], - }, - ], - n: 3, -}); +(function testTimeFieldQueryRemoveMetaField() { + testUpdate({ + initialDocList: + [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric], + updateList: [{ + q: {[timeFieldName]: dateTime}, + u: {$unset: {[metaFieldName]: ""}}, + multi: true, + }], + resultDocList: [ + { + _id: 1, + [timeFieldName]: dateTime, + }, + { + _id: 2, + [timeFieldName]: dateTime, + f: [{"k": "K", "v": "V"}], + }, + { + _id: 5, + [timeFieldName]: dateTime, + f: [2, 3], + }, + ], + nMatched: 3, + }); +})(); + +(function testRenameMetaField() { + // Rename the metaField. + testUpdate({ + initialDocList: [doc_id_3_a_b_string_metric], + updateList: [{ + q: {}, + u: {$rename: {[metaFieldName]: "Z"}}, + multi: true, + }], + resultDocList: [ + { + _id: 3, + [timeFieldName]: dateTime, + Z: {a: "A", b: "B"}, + f: "F", + }, + ], + nMatched: 1, + }); +})(); + +// Rename a subfield of the metaField to something not in the metaField. +(function testRenameMetaSubfield() { + testUpdate({ + initialDocList: [doc_id_3_a_b_string_metric], + updateList: [{ + q: {[metaFieldName + ".a"]: "A"}, + u: {$rename: {[metaFieldName + ".a"]: "Z.a"}}, + multi: true, + }], + resultDocList: [ + { + _id: 3, + [timeFieldName]: dateTime, + [metaFieldName]: {b: "B"}, + Z: {a: "A"}, + f: "F", + }, + ], + nMatched: 1, + }); +})(); // Expand a metric field. -testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric], - updateList: [{ - q: {[metaFieldName]: {a: "A", b: "B"}}, - u: {$set: {f: "x".repeat(5 * 1024 * 1024)}}, - multi: true, - }], - resultDocList: [ - { - _id: 1, - [timeFieldName]: dateTime, - [metaFieldName]: {a: "A", b: "B"}, - f: "x".repeat(5 * 1024 * 1024), - }, - { - _id: 2, - [timeFieldName]: dateTime, - [metaFieldName]: {a: "A", b: "B"}, - f: "x".repeat(5 * 1024 * 1024), - }, - ], - n: 2, -}); +(function testExpandMetricField() { + testUpdate({ + initialDocList: [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric], + updateList: [{ + q: {[metaFieldName]: {a: "A", b: "B"}}, + u: {$set: {f: "x".repeat(3 * 1024 * 1024)}}, + multi: true, + }], + resultDocList: [ + { + _id: 1, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + f: "x".repeat(3 * 1024 * 1024), + }, + { + _id: 2, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + f: "x".repeat(3 * 1024 * 1024), + }, + ], + nMatched: 2, + }); +})(); // Change the type of an existing field. -testUpdate({ - initialDocList: [doc_a_b_array_metric, doc_a_b_string_metric], - updateList: [{ - q: {[metaFieldName]: {a: "A", b: "B"}}, - u: {$set: {f: "X"}}, - multi: true, - }], - resultDocList: [ - { - _id: 2, - [timeFieldName]: dateTime, - [metaFieldName]: {a: "A", b: "B"}, - f: "X", - }, - { - _id: 3, - [timeFieldName]: dateTime, - [metaFieldName]: {a: "A", b: "B"}, - f: "X", - }, - ], - n: 2, -}); +(function testChangeExistingFieldType() { + testUpdate({ + initialDocList: [doc_id_2_a_b_array_metric, doc_id_3_a_b_string_metric], + updateList: [{ + q: {[metaFieldName]: {a: "A", b: "B"}}, + u: {$set: {f: "X"}}, + multi: true, + }], + resultDocList: [ + { + _id: 2, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + f: "X", + }, + { + _id: 3, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + f: "X", + }, + ], + nMatched: 2, + }); +})(); // Add a new field. -testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric, doc_a_b_string_metric], - updateList: [{ - q: {_id: {$lt: 3}}, - u: {$set: {g: 42}}, - multi: true, - }], - resultDocList: [ - { - _id: 1, - [timeFieldName]: dateTime, - [metaFieldName]: {a: "A", b: "B"}, - g: 42, - }, - { - _id: 2, +(function testAddNewField() { + testUpdate({ + initialDocList: + [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric, doc_id_3_a_b_string_metric], + updateList: [{ + q: {_id: {$lt: 3}}, + u: {$set: {g: 42}}, + multi: true, + }], + resultDocList: [ + { + _id: 1, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + g: 42, + }, + { + _id: 2, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", b: "B"}, + f: [{"k": "K", "v": "V"}], + g: 42, + }, + doc_id_3_a_b_string_metric + ], + nMatched: 2, + }); +})(); + +(function testArrayModifier() { + testUpdate({ + initialDocList: + [doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric, doc_id_6_a_c_array_metric], + updateList: [{ + q: {f: {$gt: 2}}, + u: {$set: {'f.$': 20}}, + multi: true, + }], + resultDocList: [ + doc_id_2_a_b_array_metric, + { + _id: 5, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", c: "C"}, + f: [2, 20], + }, + { + _id: 6, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", c: "C"}, + f: [1, 20], + } + ], + nMatched: 2, + }); +})(); + +(function testMetaFieldArrayModifier() { + testUpdate({ + initialDocList: [doc_id_8_array_meta, doc_id_2_a_b_array_metric], + updateList: [{ + q: {[metaFieldName]: {$gt: 2}}, + u: {$set: {[metaFieldName + '.$']: 20}}, + multi: true, + }], + resultDocList: [ + {_id: 8, [timeFieldName]: dateTime, [metaFieldName]: [1, 2, 20, 4]}, + doc_id_2_a_b_array_metric + ], + nMatched: 1, + }); +})(); + +(function testChangeArrayElementType() { + testUpdate({ + initialDocList: + [doc_id_2_a_b_array_metric, doc_id_5_a_c_array_metric, doc_id_6_a_c_array_metric], + updateList: [{ + q: {f: {$lte: 2}}, + u: {$set: {'f.$': {k: "v"}}}, + multi: true, + }], + resultDocList: [ + doc_id_2_a_b_array_metric, + { + _id: 5, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", c: "C"}, + f: [{k: "v"}, 3], + }, + { + _id: 6, + [timeFieldName]: dateTime, + [metaFieldName]: {a: "A", c: "C"}, + f: [{k: "v"}, 10], + } + ], + nMatched: 2, + }); +})(); + +(function testChangeMeasurementId() { + testUpdate({ + initialDocList: [doc_id_1_a_b_no_metrics], + updateList: [{ + q: {}, + u: {$set: {_id: 10}}, + multi: true, + }], + resultDocList: [{ + _id: 10, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", b: "B"}, - f: [{"k": "K", "v": "V"}], - g: 42, - }, - doc_a_b_string_metric - ], - n: 2, -}); + }], + nMatched: 1 + }); +})(); /** * Tests pipeline-style updates */ // Add a field of the sum of an array field using aggregation pipeline. testUpdate({ - initialDocList: [doc_a_c_array_metric_1, doc_a_c_array_metric_2], + initialDocList: [doc_id_5_a_c_array_metric, doc_id_6_a_c_array_metric], updateList: [{ q: {[metaFieldName]: {a: "A", c: "C"}}, u: [{$set: {sumF: {$sum: "$f"}}}], @@ -331,16 +528,16 @@ testUpdate({ _id: 6, [timeFieldName]: dateTime, [metaFieldName]: {a: "A", c: "C"}, - f: [5, 6], + f: [1, 10], sumF: 11, }, ], - n: 2, + nMatched: 2, }); // Add a new field for all measurements. testUpdate({ - initialDocList: [doc_no_meta_string_metric, doc_no_meta_int_metric], + initialDocList: [doc_id_4_no_meta_string_metric, doc_id_7_no_meta_int_metric], createCollectionWithMetaField: false, updateList: [{ q: {}, @@ -361,14 +558,14 @@ testUpdate({ newField: true, }, ], - n: 2, + nMatched: 2, }); /** * Tests upsert with multi:true. */ testUpdate({ - initialDocList: [doc_a_b_no_metrics, doc_a_b_array_metric], + initialDocList: [doc_id_1_a_b_no_metrics, doc_id_2_a_b_array_metric], updateList: [{ q: {[metaFieldName]: {z: "Z"}}, u: {$set: {[timeFieldName]: dateTime}}, @@ -376,11 +573,11 @@ testUpdate({ multi: true, }], resultDocList: [ - doc_a_b_no_metrics, - doc_a_b_array_metric, + doc_id_1_a_b_no_metrics, + doc_id_2_a_b_array_metric, {[timeFieldName]: dateTime}, ], - n: 1, + nMatched: 1, nModified: 0, }); })(); |