mirror of https://github.com/mongodb/mongo
228 lines
7.9 KiB
JavaScript
228 lines
7.9 KiB
JavaScript
/**
|
|
* Test change stream 'updateDescription' with 'showExpandedEvents'.
|
|
*/
|
|
|
|
import {assertDropAndRecreateCollection} from "jstests/libs/collection_drop_recreate.js";
|
|
import {ChangeStreamTest} from "jstests/libs/query/change_stream_util.js";
|
|
|
|
// Drop and recreate the collections to be used in this set of tests.
|
|
assertDropAndRecreateCollection(db, "coll");
|
|
|
|
const cst = new ChangeStreamTest(db);
|
|
|
|
const kLargeStr = "*".repeat(128);
|
|
assert.commandWorked(
|
|
db.coll.insert({
|
|
_id: 100,
|
|
"topLevelArray": [{subArray: [0, [0, [{bottomArray: [1, 2, kLargeStr]}]], 2, 3, kLargeStr]}],
|
|
"arrayForReplacement": [0, 1, 2, 3],
|
|
"arrayForResize": [kLargeStr, 1],
|
|
obj: {
|
|
"sub.obj": {"d.o.t.t.e.d.a.r.r.a.y..": [[{a: {"b.c": 1, field: kLargeStr}}, "truncated"]]},
|
|
},
|
|
"d.o.t.t.e.d.o.b.j.": {"sub.obj": {"b.c": 2}},
|
|
"objectWithNumericField": {"0": {"1": "numeric", field: kLargeStr}},
|
|
"arrayWithNumericField": [[{"0": "numeric", a: {"b.c": 1}, field: kLargeStr}]],
|
|
"arrayWithDotted.AndNumericFields": [[{"0": [{"1.2": {"a.b": null, c: kLargeStr}}]}]],
|
|
}),
|
|
);
|
|
|
|
const changeStreamCursor = cst.startWatchingChanges({
|
|
pipeline: [{$changeStream: {showExpandedEvents: true}}],
|
|
collection: db.coll,
|
|
});
|
|
|
|
// Test that a path which only contains non-dotted fields and array indices is not reported under
|
|
// 'disambiguatedPaths'.
|
|
assert.commandWorked(
|
|
db.coll.update(
|
|
{_id: 100},
|
|
{
|
|
$set: {"a": 2, "topLevelArray.0.subArray.1.1.0.bottomArray.2": 3, "arrayForReplacement": [0]},
|
|
},
|
|
),
|
|
);
|
|
|
|
let expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"arrayForReplacement": [0], "a": 2, "topLevelArray.0.subArray.1.1.0.bottomArray.2": 3},
|
|
removedFields: [],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Tests that an update modifying a non-array numeric field name is reported as a string rather than
|
|
// as an integer under 'disambiguatedPaths'. Array indexes are reported as integers.
|
|
assert.commandWorked(db.coll.update({_id: 100}, {$set: {"arrayWithNumericField.0.0.1": {"b.c": 1}}}));
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"arrayWithNumericField.0.0.1": {"b.c": 1}},
|
|
removedFields: [],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {"arrayWithNumericField.0.0.1": ["arrayWithNumericField", 0, 0, "1"]},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Tests that an update modifying a non-array numeric field name is reported when no array indices
|
|
// or dotted fields are present.
|
|
assert.commandWorked(db.coll.update({_id: 100}, {$set: {"objectWithNumericField.0.1": "updated"}}));
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"objectWithNumericField.0.1": "updated"},
|
|
removedFields: [],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {"objectWithNumericField.0.1": ["objectWithNumericField", "0", "1"]},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Tests that an update with $unset array does not report the array under 'disambiguatedPaths'.
|
|
assert.commandWorked(db.coll.update({_id: 100}, [{$unset: ["arrayForReplacement"]}]));
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {},
|
|
removedFields: ["arrayForReplacement"],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Tests that an update with 'truncatedArrays' does not report the array under 'disambiguatedPaths'.
|
|
assert.commandWorked(
|
|
db.coll.update({_id: 100}, [
|
|
{$replaceWith: {$setField: {field: "arrayForResize", input: "$$ROOT", value: [kLargeStr]}}},
|
|
]),
|
|
);
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {},
|
|
removedFields: [],
|
|
truncatedArrays: [{field: "arrayForResize", newSize: 1}],
|
|
disambiguatedPaths: {},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Verify that top-level dotted fields are reported under 'disambiguatedPaths'.
|
|
assert.commandWorked(
|
|
db.coll.update({_id: 100}, [
|
|
{
|
|
$replaceWith: {$setField: {field: "d.o.t.t.e.d.o.b.j.", input: "$$ROOT", value: {"subObj": 1}}},
|
|
},
|
|
{$replaceWith: {$setField: {field: "new.Field.", input: "$$ROOT", value: 1}}},
|
|
]),
|
|
);
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"d.o.t.t.e.d.o.b.j.": {subObj: 1}, "new.Field.": 1},
|
|
removedFields: [],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {"d.o.t.t.e.d.o.b.j.": ["d.o.t.t.e.d.o.b.j."], "new.Field.": ["new.Field."]},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Test that a combination of dotted fields and array indices are reported in 'disambiguatedPaths'.
|
|
assert.commandWorked(
|
|
db.coll.update({_id: 100}, [
|
|
{
|
|
$set: {
|
|
obj: {
|
|
$setField: {
|
|
field: "sub.obj",
|
|
input: "$obj",
|
|
value: {
|
|
$literal: {"d.o.t.t.e.d.a.r.r.a.y..": [[{a: {"b.c": 2, field: kLargeStr}}]]},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
]),
|
|
);
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"obj.sub.obj.d.o.t.t.e.d.a.r.r.a.y...0.0.a.b.c": 2},
|
|
removedFields: [],
|
|
truncatedArrays: [{field: "obj.sub.obj.d.o.t.t.e.d.a.r.r.a.y...0", newSize: 1}],
|
|
disambiguatedPaths: {
|
|
"obj.sub.obj.d.o.t.t.e.d.a.r.r.a.y...0": ["obj", "sub.obj", "d.o.t.t.e.d.a.r.r.a.y..", 0],
|
|
"obj.sub.obj.d.o.t.t.e.d.a.r.r.a.y...0.0.a.b.c": [
|
|
"obj",
|
|
"sub.obj",
|
|
"d.o.t.t.e.d.a.r.r.a.y..",
|
|
0,
|
|
0,
|
|
"a",
|
|
"b.c",
|
|
],
|
|
},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
// Test that an update which modifies a path containing dotted, numeric and array index fields
|
|
// distinguishes all three in 'disambiguatedPaths'.
|
|
assert.commandWorked(
|
|
db.coll.update({_id: 100}, [
|
|
{
|
|
$replaceWith: {
|
|
$setField: {
|
|
field: "arrayWithDotted.AndNumericFields",
|
|
input: "$$ROOT",
|
|
value: {$literal: [[{"0": [{"1.2": {"a.b": true, c: kLargeStr}}]}]]},
|
|
},
|
|
},
|
|
},
|
|
]),
|
|
);
|
|
expected = {
|
|
documentKey: {_id: 100},
|
|
ns: {db: "test", coll: "coll"},
|
|
operationType: "update",
|
|
updateDescription: {
|
|
updatedFields: {"arrayWithDotted.AndNumericFields.0.0.0.0.1.2.a.b": true},
|
|
removedFields: [],
|
|
truncatedArrays: [],
|
|
disambiguatedPaths: {
|
|
"arrayWithDotted.AndNumericFields.0.0.0.0.1.2.a.b": [
|
|
"arrayWithDotted.AndNumericFields",
|
|
0,
|
|
0,
|
|
"0",
|
|
0,
|
|
"1.2",
|
|
"a.b",
|
|
],
|
|
},
|
|
},
|
|
};
|
|
cst.assertNextChangesEqual({cursor: changeStreamCursor, expectedChanges: [expected]});
|
|
|
|
cst.cleanUp();
|