From 72dc6ea464cf90800fa5669c9b39fa466691ae02 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Wed, 17 Aug 2022 11:48:00 -0400 Subject: [PATCH 1/6] add disambiguatedPaths to change streams update document --- source/change-streams/change-streams.rst | 22 +- .../change-streams-disambiguatedPaths.json | 250 ++++++++++++++++++ .../change-streams-disambiguatedPaths.yml | 102 +++++++ 3 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 source/change-streams/tests/unified/change-streams-disambiguatedPaths.json create mode 100644 source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index da24213995..3451cefea1 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -307,12 +307,32 @@ If an aggregate command with a ``$changeStream`` stage completes successfully, t * @since 4.7.0 */ truncatedArrays: Array; + + /** + * A document containing a map that associates an update path to an array containing the path components used in the update document. This data + * can be used in combination with the other fields in an `UpdateDescription` to determine the actual path in the document that was updated. This is + * necessary in cases where a key contains a dot-separated strings (i.e., `{ "a.b": "c" }`) or a document contains a numeric literal string key + * (i.e., `{ "a": { "0": "a" } }`. Note that in this scenario, the numeric key can't be the top level key, because `{ "0": "a" }` is not ambiguous - + * update paths would simply be `'0'` which is unambiguous because BSON documents cannot have arrays at the top level.). + * + * Each entry in the document maps an update path to an array which contains the actual path used when the document was updated. + * For example, given a document with the following shape `{ "a": { "0": 0 } }` and an update of `{ $inc: { "a.0": 1 } }`, `disambiguatedPaths` would + * look like the following: + * { + * "a.0": ["a", "0"] + * } + * + * In each array, all elements will be returned as strings with the exception of array indices, which will be returned as 32 bit integers. + * + * @since 6.1.0 + */ + disambiguatedPaths?: Document } The responses to a change stream aggregate or getMore have the following structures: .. code:: typescript - +spo /** * Response to a successful aggregate. */ diff --git a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json new file mode 100644 index 0000000000..b53ff41c74 --- /dev/null +++ b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json @@ -0,0 +1,250 @@ +{ + "description": "disambiguatedPaths", + "schemaVersion": "1.9", + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "database0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "collection0" + } + } + ], + "runOnRequirements": [ + { + "minServerVersion": "6.1.0", + "topologies": [ + "replicaset", + "sharded-replicaset", + "load-balanced" + ] + } + ], + "initialData": [ + { + "collectionName": "collection0", + "databaseName": "database0", + "documents": [] + } + ], + "tests": [ + { + "description": "disambiguatedPaths is not present when showExpandedEvents is false/unset", + "operations": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 1, + "a": { + "1": 1 + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [] + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "a.1": 2 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "database0", + "coll": "collection0" + }, + "updateDescription": { + "updatedFields": { + "$$exists": true + }, + "removedFields": { + "$$exists": true + }, + "truncatedArrays": { + "$$exists": true + }, + "disambiguatedPaths": { + "$$exists": false + } + } + } + } + ] + }, + { + "description": "disambiguatedPaths is present on updateDescription when an ambiguous path is present", + "operations": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 1, + "a": { + "1": 1 + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "showExpandedEvents": true + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "a.1": 2 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "database0", + "coll": "collection0" + }, + "updateDescription": { + "updatedFields": { + "$$exists": true + }, + "removedFields": { + "$$exists": true + }, + "truncatedArrays": { + "$$exists": true + }, + "disambiguatedPaths": { + "a.1": [ + "a", + "1" + ] + } + } + } + } + ] + }, + { + "description": "disambiguatedPaths returns array indices as integers", + "operations": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 1, + "a": [ + { + "1": 1 + } + ] + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "showExpandedEvents": true + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "a.0.1": 2 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "database0", + "coll": "collection0" + }, + "updateDescription": { + "updatedFields": { + "$$exists": true + }, + "removedFields": { + "$$exists": true + }, + "truncatedArrays": { + "$$exists": true + }, + "disambiguatedPaths": { + "a.0.1": [ + "a", + { + "$$type": "int" + }, + "1" + ] + } + } + } + } + ] + } + ] +} diff --git a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml new file mode 100644 index 0000000000..59e2f8966a --- /dev/null +++ b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml @@ -0,0 +1,102 @@ +description: "disambiguatedPaths" +schemaVersion: "1.9" +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false + - database: + id: &database0 database0 + client: *client0 + databaseName: *database0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: *collection0 + +runOnRequirements: + - minServerVersion: "6.1.0" + topologies: [ replicaset, sharded-replicaset, load-balanced ] + +initialData: + - collectionName: *collection0 + databaseName: *database0 + documents: [] + +tests: + - description: "disambiguatedPaths is not present when showExpandedEvents is false/unset" + operations: + - name: insertOne + object: *collection0 + arguments: + document: { _id: 1, 'a': { '1': 1 } } + - name: createChangeStream + object: *collection0 + arguments: { pipeline: [] } + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { 'a.1': 2 } } + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0, coll: *collection0 } + updateDescription: + updatedFields: { $$exists: true } + removedFields: { $$exists: true } + truncatedArrays: { $$exists: true } + disambiguatedPaths: { $$exists: false } + + - description: "disambiguatedPaths is present on updateDescription when an ambiguous path is present" + operations: + - name: insertOne + object: *collection0 + arguments: + document: { _id: 1, 'a': { '1': 1 } } + - name: createChangeStream + object: *collection0 + arguments: { pipeline: [], showExpandedEvents: true } + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { 'a.1': 2 } } + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0, coll: *collection0 } + updateDescription: + updatedFields: { $$exists: true } + removedFields: { $$exists: true } + truncatedArrays: { $$exists: true } + disambiguatedPaths: { 'a.1': ['a', '1'] } + + - description: "disambiguatedPaths returns array indices as integers" + operations: + - name: insertOne + object: *collection0 + arguments: + document: { _id: 1, 'a': [{'1': 1 }] } + - name: createChangeStream + object: *collection0 + arguments: { pipeline: [], showExpandedEvents: true } + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { 'a.0.1': 2 } } + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0, coll: *collection0 } + updateDescription: + updatedFields: { $$exists: true } + removedFields: { $$exists: true } + truncatedArrays: { $$exists: true } + disambiguatedPaths: { 'a.0.1': ['a', { $$type: 'int' }, '1'] } From 4c9b1739bac48b934d1083d52d6a8d4b902f6fcc Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Wed, 17 Aug 2022 11:52:41 -0400 Subject: [PATCH 2/6] chore: update changelog and bump spec version --- source/change-streams/change-streams.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index 3451cefea1..e416396790 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -10,7 +10,7 @@ Change Streams :Type: Standards :Minimum Server Version: 3.6 :Last Modified: 2022-05-19 -:Version: 1.16 +:Version: 1.17 .. contents:: @@ -1090,3 +1090,5 @@ Changelog +------------+------------------------------------------------------------+ | 2022-05-19 | Support new change stream events with showExpandedEvents. | +------------+------------------------------------------------------------+ +| 2022-08-17 | Support `disambiguatedPaths` in `UpdateDescription`. | ++------------+------------------------------------------------------------+ From fcca0f8d1b64007f1416a0324ec18f6c7bb74cb7 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Wed, 17 Aug 2022 13:34:13 -0400 Subject: [PATCH 3/6] chore: remove unintentional change --- source/change-streams/change-streams.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index e416396790..d0caa7b0d6 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -332,7 +332,6 @@ If an aggregate command with a ``$changeStream`` stage completes successfully, t The responses to a change stream aggregate or getMore have the following structures: .. code:: typescript -spo /** * Response to a successful aggregate. */ From 2cd8cffe8b9454c86c410894daee13e4e2ac6994 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Wed, 17 Aug 2022 13:34:39 -0400 Subject: [PATCH 4/6] chore: remove unintentional change --- source/change-streams/change-streams.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index d0caa7b0d6..128346c06a 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -332,6 +332,7 @@ If an aggregate command with a ``$changeStream`` stage completes successfully, t The responses to a change stream aggregate or getMore have the following structures: .. code:: typescript + /** * Response to a successful aggregate. */ From 30236427453b008f6932ce6d0df6babff5a4a2fb Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Thu, 18 Aug 2022 15:36:06 -0400 Subject: [PATCH 5/6] Address Benji's comment - fix double space typos - lower schema veresion to 1.3 instead of 1.9 - add `sharded` to list of supported topoligies - remove ? in type definition in favor of the `Optional` keyword --- source/change-streams/change-streams.rst | 8 ++++---- .../tests/unified/change-streams-disambiguatedPaths.json | 5 +++-- .../tests/unified/change-streams-disambiguatedPaths.yml | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index 128346c06a..2ff0640b9f 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -309,10 +309,10 @@ If an aggregate command with a ``$changeStream`` stage completes successfully, t truncatedArrays: Array; /** - * A document containing a map that associates an update path to an array containing the path components used in the update document. This data + * A document containing a map that associates an update path to an array containing the path components used in the update document. This data * can be used in combination with the other fields in an `UpdateDescription` to determine the actual path in the document that was updated. This is - * necessary in cases where a key contains a dot-separated strings (i.e., `{ "a.b": "c" }`) or a document contains a numeric literal string key - * (i.e., `{ "a": { "0": "a" } }`. Note that in this scenario, the numeric key can't be the top level key, because `{ "0": "a" }` is not ambiguous - + * necessary in cases where a key contains dot-separated strings (i.e., `{ "a.b": "c" }`) or a document contains a numeric literal string key + * (i.e., `{ "a": { "0": "a" } }`. Note that in this scenario, the numeric key can't be the top level key, because `{ "0": "a" }` is not ambiguous - * update paths would simply be `'0'` which is unambiguous because BSON documents cannot have arrays at the top level.). * * Each entry in the document maps an update path to an array which contains the actual path used when the document was updated. @@ -326,7 +326,7 @@ If an aggregate command with a ``$changeStream`` stage completes successfully, t * * @since 6.1.0 */ - disambiguatedPaths?: Document + disambiguatedPaths: Optional } The responses to a change stream aggregate or getMore have the following structures: diff --git a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json index b53ff41c74..9a639801ee 100644 --- a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json +++ b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.json @@ -1,6 +1,6 @@ { "description": "disambiguatedPaths", - "schemaVersion": "1.9", + "schemaVersion": "1.3", "createEntities": [ { "client": { @@ -29,7 +29,8 @@ "topologies": [ "replicaset", "sharded-replicaset", - "load-balanced" + "load-balanced", + "sharded" ] } ], diff --git a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml index 59e2f8966a..674c876b02 100644 --- a/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml +++ b/source/change-streams/tests/unified/change-streams-disambiguatedPaths.yml @@ -1,5 +1,5 @@ description: "disambiguatedPaths" -schemaVersion: "1.9" +schemaVersion: "1.3" createEntities: - client: id: &client0 client0 @@ -15,7 +15,7 @@ createEntities: runOnRequirements: - minServerVersion: "6.1.0" - topologies: [ replicaset, sharded-replicaset, load-balanced ] + topologies: [ replicaset, sharded-replicaset, load-balanced, sharded ] initialData: - collectionName: *collection0 From f898171de2ee49aee13ae0c82baf3f093087fa20 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Thu, 18 Aug 2022 22:30:48 -0400 Subject: [PATCH 6/6] chore: bump updated at date --- source/change-streams/change-streams.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/change-streams/change-streams.rst b/source/change-streams/change-streams.rst index 2ff0640b9f..fd8c875d6a 100644 --- a/source/change-streams/change-streams.rst +++ b/source/change-streams/change-streams.rst @@ -9,7 +9,7 @@ Change Streams :Status: Accepted :Type: Standards :Minimum Server Version: 3.6 -:Last Modified: 2022-05-19 +:Last Modified: 2022-08-18 :Version: 1.17 .. contents::