summaryrefslogtreecommitdiff
path: root/jstests/aggregation
diff options
context:
space:
mode:
authorAnton Korshunov <anton.korshunov@mongodb.com>2019-03-25 16:20:25 +0000
committerAnton Korshunov <anton.korshunov@mongodb.com>2019-05-02 17:03:31 +0100
commitfc6c65c0d4ffff4104e355af6f6c3d73b79ad713 (patch)
treee17af8d59a97450d965190c9f16c51376538ef24 /jstests/aggregation
parent923bb8465cf13a81c90ca3002e5386411ce5d14b (diff)
downloadmongo-fc6c65c0d4ffff4104e355af6f6c3d73b79ad713.tar.gz
SERVER-40429 Add merge stage to write output to existing collection
Diffstat (limited to 'jstests/aggregation')
-rw-r--r--jstests/aggregation/sources/explain_out.js2
-rw-r--r--jstests/aggregation/sources/merge/all_modes.js71
-rw-r--r--jstests/aggregation/sources/out/exchange_explain.js4
-rw-r--r--jstests/aggregation/sources/out/mode_replace_documents.js6
-rw-r--r--jstests/aggregation/sources/out/unique_key_requires_index.js2
-rw-r--r--jstests/aggregation/sources/out/unique_key_validation.js18
6 files changed, 87 insertions, 16 deletions
diff --git a/jstests/aggregation/sources/explain_out.js b/jstests/aggregation/sources/explain_out.js
index bec7a83765e..9304afcec67 100644
--- a/jstests/aggregation/sources/explain_out.js
+++ b/jstests/aggregation/sources/explain_out.js
@@ -44,7 +44,7 @@
explain: {aggregate: sourceColl.getName(), pipeline: [outStage], cursor: {}},
verbosity: verbosity
}),
- 51029);
+ [51029, 51184]);
assert.eq(targetColl.find().itcount(), 0);
}
diff --git a/jstests/aggregation/sources/merge/all_modes.js b/jstests/aggregation/sources/merge/all_modes.js
new file mode 100644
index 00000000000..bb21b24029f
--- /dev/null
+++ b/jstests/aggregation/sources/merge/all_modes.js
@@ -0,0 +1,71 @@
+// Tests basic use cases for all $merge modes.
+(function() {
+ "use strict";
+
+ load("jstests/aggregation/extras/utils.js"); // For arrayEq.
+
+ // Asserts that two arrays are equal - that is, if their sizes are equal and each element in
+ // the 'actual' array has a matching element in the 'expected' array, without honoring
+ // elements order.
+ function assertArrayEq({actual = [], expected = []} = {}) {
+ assert(arrayEq(actual, expected), `actual=${tojson(actual)}, expected=${tojson(expected)}`);
+ }
+
+ const source = db.all_modes_source;
+ const target = db.all_modes_target;
+
+ (function setup() {
+ source.drop();
+ target.drop();
+
+ // All tests use the same data in the source collection.
+ assert.commandWorked(source.insert(
+ [{_id: 1, a: 1, b: "a"}, {_id: 2, a: 2, b: "b"}, {_id: 3, a: 3, b: "c"}]));
+
+ })();
+
+ // Test 'whenMatched=fail whenNotMatched=insert' mode. This is an equivalent of a
+ // replacemnt-style update with upsert=true.
+ (function testWhenMatchedReplaceWithNewWhenNotMatchedInsert() {
+ assert.commandWorked(target.insert([{_id: 1, a: 10}, {_id: 3, a: 30}, {_id: 4, a: 40}]));
+ assert.doesNotThrow(() => source.aggregate([{
+ $merge: {
+ into: target.getName(),
+ whenMatched: "replaceWithNew",
+ whenNotMatched: "insert"
+ }
+ }]));
+ assertArrayEq({
+ actual: target.find().toArray(),
+ expected: [
+ {_id: 1, a: 1, b: "a"},
+ {_id: 2, a: 2, b: "b"},
+ {_id: 3, a: 3, b: "c"},
+ {_id: 4, a: 40}
+ ]
+ });
+ })();
+
+ // Test 'whenMatched=fail whenNotMatched=insert' mode. For matched documents the update should
+ // be unordered and report an error at the end when all documents in a batch have been
+ // processed, it will not fail as soon as we hit the first document without a match.
+ (function testWhenMatchedFailWhenNotMatchedInsert() {
+ assert(target.drop());
+ assert.commandWorked(target.insert(
+ [{_id: 10, a: 10, c: "x"}, {_id: 3, a: 30, c: "y"}, {_id: 4, a: 40, c: "z"}]));
+ const error = assert.throws(() => source.aggregate([
+ {$merge: {into: target.getName(), whenMatched: "fail", whenNotMatched: "insert"}}
+ ]));
+ assert.commandFailedWithCode(error, ErrorCodes.DuplicateKey);
+ assertArrayEq({
+ actual: target.find().toArray(),
+ expected: [
+ {_id: 1, a: 1, b: "a"},
+ {_id: 2, a: 2, b: "b"},
+ {_id: 3, a: 30, c: "y"},
+ {_id: 4, a: 40, c: "z"},
+ {_id: 10, a: 10, c: "x"}
+ ]
+ });
+ })();
+}());
diff --git a/jstests/aggregation/sources/out/exchange_explain.js b/jstests/aggregation/sources/out/exchange_explain.js
index 84a5b02588f..ebf85336677 100644
--- a/jstests/aggregation/sources/out/exchange_explain.js
+++ b/jstests/aggregation/sources/out/exchange_explain.js
@@ -105,7 +105,7 @@ load('jstests/aggregation/extras/utils.js');
mode: "replaceDocuments"
}
}],
- 50905);
+ 51132);
// Turn off the exchange and rerun the query.
assert.commandWorked(mongosDB.adminCommand({setParameter: 1, internalQueryDisableExchange: 1}));
@@ -126,7 +126,7 @@ load('jstests/aggregation/extras/utils.js');
mode: "replaceDocuments"
}
}],
- 50905);
+ 51132);
// SERVER-38349 Make sure mongos rejects specifying exchange directly.
assert.commandFailedWithCode(mongosDB.runCommand({
diff --git a/jstests/aggregation/sources/out/mode_replace_documents.js b/jstests/aggregation/sources/out/mode_replace_documents.js
index 4281b2b7c08..269d3ca2109 100644
--- a/jstests/aggregation/sources/out/mode_replace_documents.js
+++ b/jstests/aggregation/sources/out/mode_replace_documents.js
@@ -97,7 +97,7 @@
assertErrorCode(
coll,
[{$out: {to: outColl.getName(), mode: "replaceDocuments", uniqueKey: {missing: 1}}}],
- 50905 // This attempt should fail because there's no field 'missing' in the document.
+ 51132 // This attempt should fail because there's no field 'missing' in the document.
);
// Test that a replace fails to insert a document if it violates a unique index constraint. In
@@ -123,7 +123,7 @@
{$addFields: {_id: 0}},
{$out: {to: outColl.getName(), mode: "replaceDocuments", uniqueKey: {_id: 1, "a.b": 1}}}
],
- 50905);
+ 51132);
coll.drop();
assert.commandWorked(coll.insert({_id: 0, a: [{b: 1}]}));
@@ -133,7 +133,7 @@
{$addFields: {_id: 0}},
{$out: {to: outColl.getName(), mode: "replaceDocuments", uniqueKey: {_id: 1, "a.b": 1}}}
],
- 50905);
+ 51132);
// Tests for $out to a database that differs from the aggregation database.
const foreignDb = db.getSiblingDB("mode_replace_documents_foreign");
diff --git a/jstests/aggregation/sources/out/unique_key_requires_index.js b/jstests/aggregation/sources/out/unique_key_requires_index.js
index 5d42626e7a1..6448fcd5074 100644
--- a/jstests/aggregation/sources/out/unique_key_requires_index.js
+++ b/jstests/aggregation/sources/out/unique_key_requires_index.js
@@ -282,7 +282,7 @@
],
cursor: {}
}),
- 50905);
+ [50905, 51132]);
});
}());
diff --git a/jstests/aggregation/sources/out/unique_key_validation.js b/jstests/aggregation/sources/out/unique_key_validation.js
index 9af0486f7dd..73d3a49c29b 100644
--- a/jstests/aggregation/sources/out/unique_key_validation.js
+++ b/jstests/aggregation/sources/out/unique_key_validation.js
@@ -66,15 +66,15 @@
[{$out: {to: target.getName(), mode: "replaceDocuments", uniqueKey: {name: 1, team: 1}}}];
// Missing both "name" and "team".
- assertErrorCode(source, pipelineNameTeam, 50905);
+ assertErrorCode(source, pipelineNameTeam, 51132);
// Missing "name".
assert.commandWorked(source.update({_id: 0}, {_id: 0, team: "query"}));
- assertErrorCode(source, pipelineNameTeam, 50905);
+ assertErrorCode(source, pipelineNameTeam, 51132);
// Missing "team".
assert.commandWorked(source.update({_id: 0}, {_id: 0, name: "nicholas"}));
- assertErrorCode(source, pipelineNameTeam, 50905);
+ assertErrorCode(source, pipelineNameTeam, 51132);
// A document with both "name" and "team" will be accepted.
assert.commandWorked(source.update({_id: 0}, {_id: 0, name: "nicholas", team: "query"}));
@@ -92,19 +92,19 @@
// Explicit null "song" (a prefix of a "uniqueKey" field).
assert.commandWorked(source.update({_id: 0}, {_id: 0, song: null}));
- assertErrorCode(source, pipelineSongDotArtist, 50905);
+ assertErrorCode(source, pipelineSongDotArtist, 51132);
// Explicit undefined "song" (a prefix of a "uniqueKey" field).
assert.commandWorked(source.update({_id: 0}, {_id: 0, song: undefined}));
- assertErrorCode(source, pipelineSongDotArtist, 50905);
+ assertErrorCode(source, pipelineSongDotArtist, 51132);
// Explicit null "song.artist".
assert.commandWorked(source.update({_id: 0}, {_id: 0, song: {artist: null}}));
- assertErrorCode(source, pipelineSongDotArtist, 50905);
+ assertErrorCode(source, pipelineSongDotArtist, 51132);
// Explicit undefined "song.artist".
assert.commandWorked(source.update({_id: 0}, {_id: 0, song: {artist: undefined}}));
- assertErrorCode(source, pipelineSongDotArtist, 50905);
+ assertErrorCode(source, pipelineSongDotArtist, 51132);
// A valid "artist" will be accepted.
assert.commandWorked(source.update({_id: 0}, {_id: 0, song: {artist: "Illenium"}}));
@@ -124,11 +124,11 @@
// "address.street" is an array.
assert.commandWorked(
source.update({_id: 0}, {_id: 0, address: {street: ["West 43rd St", "1633 Broadway"]}}));
- assertErrorCode(source, pipelineAddressDotStreet, 50943);
+ assertErrorCode(source, pipelineAddressDotStreet, 51185);
// "address" is an array (a prefix of a "uniqueKey" field).
assert.commandWorked(source.update({_id: 0}, {_id: 0, address: [{street: "1633 Broadway"}]}));
- assertErrorCode(source, pipelineAddressDotStreet, 50905);
+ assertErrorCode(source, pipelineAddressDotStreet, 51132);
// A scalar "address.street" is accepted.
assert.commandWorked(source.update({_id: 0}, {_id: 0, address: {street: "1633 Broadway"}}));