summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlison Lu <alison.lu@mongodb.com>2021-07-20 17:51:38 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-07-21 13:59:22 +0000
commit8981461aab4dfe5cc4b0130f90182cbea556fb50 (patch)
tree378cdcf33ed261d83ca93092b9cab1d178678e26
parent58f0b2a63c61656314f1931158fe9d18488673e4 (diff)
downloadmongo-8981461aab4dfe5cc4b0130f90182cbea556fb50.tar.gz
SERVER-58617 Allow updates on time-series collections with no metaField
-rw-r--r--jstests/core/timeseries/timeseries_update.js52
-rw-r--r--src/mongo/db/commands/write_commands.cpp12
-rw-r--r--src/mongo/db/timeseries/timeseries_update_delete_util.cpp20
3 files changed, 61 insertions, 23 deletions
diff --git a/jstests/core/timeseries/timeseries_update.js b/jstests/core/timeseries/timeseries_update.js
index d5a7cb95280..578b0928b74 100644
--- a/jstests/core/timeseries/timeseries_update.js
+++ b/jstests/core/timeseries/timeseries_update.js
@@ -32,6 +32,11 @@ const doc2 = {
[metaFieldName]: {c: "C", d: 2},
f: [{"k": "K", "v": "V"}],
};
+const doc3 = {
+ _id: 3,
+ [timeFieldName]: dateTime,
+ f: "F",
+};
TimeseriesTest.run((insert) => {
const testDB = db.getSiblingDB(jsTestName());
@@ -46,11 +51,14 @@ TimeseriesTest.run((insert) => {
resultDocList,
nModified = 0,
failCode = null,
+ hasMetaField = true,
ordered = true
}) {
const coll = testDB.getCollection('t');
- assert.commandWorked(testDB.createCollection(
- coll.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
+ assert.commandWorked(testDB.createCollection(coll.getName(), {
+ timeseries: hasMetaField ? {timeField: timeFieldName, metaField: metaFieldName}
+ : {timeField: timeFieldName},
+ }));
assert.commandWorked(insert(coll, initialDocList));
const updateCommand = {update: coll.getName(), updates: updateList};
@@ -391,5 +399,45 @@ TimeseriesTest.run((insert) => {
resultDocList: [doc2],
failCode: ErrorCodes.InvalidOptions,
});
+
+ /*********************** Tests updating a collection with no metaField. **********************/
+ // Query on a field which is not the (nonexistent) metaField.
+ testUpdate({
+ initialDocList: [doc3],
+ updateList: [{
+ q: {f: "F"},
+ u: {},
+ multi: true,
+ }],
+ resultDocList: [doc3],
+ failCode: ErrorCodes.InvalidOptions,
+ hasMetaField: false,
+ });
+
+ // Query on all documents and update them to be empty documents.
+ testUpdate({
+ initialDocList: [doc3],
+ updateList: [{
+ q: {},
+ u: {},
+ multi: true,
+ }],
+ resultDocList: [doc3],
+ failCode: ErrorCodes.InvalidOptions,
+ hasMetaField: false,
+ });
+
+ // Query on all documents and update them to be nonempty documents.
+ testUpdate({
+ initialDocList: [doc3],
+ updateList: [{
+ q: {},
+ u: {f: "FF"},
+ multi: true,
+ }],
+ resultDocList: [doc3],
+ failCode: ErrorCodes.InvalidOptions,
+ hasMetaField: false,
+ });
});
}());
diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp
index c14430d94e2..1397fe6ce09 100644
--- a/src/mongo/db/commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands.cpp
@@ -1315,14 +1315,7 @@ public:
"Time-series buckets collection is missing time-series options",
timeseriesOptions);
- // TODO: SERVER-58617 Allow updates on time-series collections with no metaField.
- uassert(
- ErrorCodes::IllegalOperation,
- str::stream()
- << "Updates on a time-series collection without a metaField are not supported: "
- << ns(),
- timeseriesOptions->getMetaField() != boost::none);
- StringData metaField = *timeseriesOptions->getMetaField();
+ StringData metaField = timeseriesOptions->getMetaField().value_or("");
// Create the translated updates to apply, which are used to make a new
// UpdateCommandRequest.
@@ -1537,8 +1530,7 @@ public:
uassert(ErrorCodes::InvalidOptions,
"Time-series buckets collection is missing time-series options",
timeseriesOptions);
- StringData metaField =
- timeseriesOptions->getMetaField() ? *timeseriesOptions->getMetaField() : "";
+ StringData metaField = timeseriesOptions->getMetaField().value_or("");
std::vector<mongo::write_ops::DeleteOpEntry> timeseriesDeletes;
timeseriesDeletes.reserve(request().getDeletes().size());
diff --git a/src/mongo/db/timeseries/timeseries_update_delete_util.cpp b/src/mongo/db/timeseries/timeseries_update_delete_util.cpp
index ed5f4520422..5eafea0d762 100644
--- a/src/mongo/db/timeseries/timeseries_update_delete_util.cpp
+++ b/src/mongo/db/timeseries/timeseries_update_delete_util.cpp
@@ -63,9 +63,7 @@ std::string getRenamedMetaField(StringData field) {
* Replaces the first occurrence of the metaField in the given field of the given mutablebson
* element with the literal "meta", accounting for uses of the metaField with dot notation.
*/
-void replaceTimeseriesQueryMetaFieldName(mutablebson::Element elem,
- StringData field,
- StringData metaField) {
+void replaceQueryMetaFieldName(mutablebson::Element elem, StringData field, StringData metaField) {
if (isMetaFieldFirstElementOfDottedPathField(field, metaField)) {
invariantStatusOK(elem.rename(getRenamedMetaField(field)));
}
@@ -74,12 +72,12 @@ void replaceTimeseriesQueryMetaFieldName(mutablebson::Element elem,
/**
* Recurses through the mutablebson element query and replaces any occurrences of the
* metaField with "meta" accounting for queries that may be in dot notation. shouldReplaceFieldValue
- * is set for $expr queries when "$" + the metaField should be subsitutited for "$meta".
+ * is set for $expr queries when "$" + the metaField should be substituted for "$meta".
*/
-void replaceTimeseriesQueryMetaFieldName(mutablebson::Element elem, StringData metaField) {
- replaceTimeseriesQueryMetaFieldName(elem, elem.getFieldName(), metaField);
+void replaceQueryMetaFieldName(mutablebson::Element elem, StringData metaField) {
+ replaceQueryMetaFieldName(elem, elem.getFieldName(), metaField);
for (size_t i = 0; i < elem.countChildren(); ++i) {
- replaceTimeseriesQueryMetaFieldName(elem.findNthChild(i), metaField);
+ replaceQueryMetaFieldName(elem.findNthChild(i), metaField);
}
}
} // namespace
@@ -166,7 +164,7 @@ bool updateOnlyModifiesMetaField(OperationContext* opCtx,
BSONObj translateQuery(const BSONObj& query, StringData metaField) {
invariant(!metaField.empty());
mutablebson::Document queryDoc(query);
- timeseries::replaceTimeseriesQueryMetaFieldName(queryDoc.root(), metaField);
+ timeseries::replaceQueryMetaFieldName(queryDoc.root(), metaField);
return queryDoc.getObject();
}
@@ -197,7 +195,7 @@ write_ops::UpdateOpEntry translateUpdate(const BSONObj& translatedQuery,
// and replace it if it is the metaField.
for (size_t j = 0; j < updatePair.countChildren(); j++) {
auto fieldValuePair = updatePair.findNthChild(j);
- timeseries::replaceTimeseriesQueryMetaFieldName(
+ timeseries::replaceQueryMetaFieldName(
fieldValuePair, fieldValuePair.getFieldName(), metaField);
}
}
@@ -223,14 +221,14 @@ write_ops::UpdateOpEntry translateUpdate(const BSONObj& translatedQuery,
// updatePair = $set: {<newField> : <newExpression>, ...}
for (size_t j = 0; j < updatePair.countChildren(); j++) {
auto fieldValuePair = updatePair.findNthChild(j);
- timeseries::replaceTimeseriesQueryMetaFieldName(
+ timeseries::replaceQueryMetaFieldName(
fieldValuePair, fieldValuePair.getFieldName(), metaField);
}
} else if (aggOp == "$unset" || aggOp == "$project") {
if (updatePair.getType() == BSONType::Array) {
// updatePair = $unset: ["field1", "field2", ...]
for (size_t j = 0; j < updatePair.countChildren(); j++) {
- timeseries::replaceTimeseriesQueryMetaFieldName(
+ timeseries::replaceQueryMetaFieldName(
updatePair,
updatePair.findNthChild(j).getValueString(),
metaField);