mirror of https://github.com/mongodb/mongo
113 lines
3.7 KiB
JavaScript
113 lines
3.7 KiB
JavaScript
/**
|
|
* This is the test for $documents stage along with $merge stage in an aggregation pipeline,
|
|
* including verifying the bug in SERVER-85892 is addressed when the spec 'whenMatched' is not
|
|
* empty.
|
|
*
|
|
* @tags: [
|
|
* assumes_against_mongod_not_mongos, # not yet supported until 7.2 with SERVER-65534
|
|
* ]
|
|
*/
|
|
|
|
load("jstests/aggregation/extras/merge_helpers.js"); // For withEachMergeMode and
|
|
// dropWithoutImplicitRecreate.
|
|
|
|
const outColl = db[`${jsTest.name()}_out`];
|
|
const outCollName = outColl.getName();
|
|
const expectedTotalDocs = 100;
|
|
|
|
function assertDocsInsertedCorrectly(docs, pipeline) {
|
|
const msg = `Failed with pipeline: ${JSON.stringify(pipeline, null, 2)}`;
|
|
|
|
assert.eq(expectedTotalDocs, docs.length, msg);
|
|
for (let i = 0; i < expectedTotalDocs; i++) {
|
|
assert.eq(docs[i].x, i, msg);
|
|
}
|
|
}
|
|
|
|
const documentsStage = {
|
|
$documents: {$map: {input: {$range: [0, expectedTotalDocs]}, in : {x: "$$this"}}}
|
|
};
|
|
|
|
function testFn(pipeline, assertFn) {
|
|
// Creates an index as $merge requires a unique index with the 'on' identifier field. Then
|
|
// inserts a document allowed to be matched.
|
|
dropWithoutImplicitRecreate(outCollName);
|
|
assert.commandWorked(outColl.createIndex({x: 1}, {unique: true}));
|
|
assert.commandWorked(outColl.insert({x: 10}));
|
|
|
|
assert.doesNotThrow(() => db.aggregate(pipeline));
|
|
let res = outColl.find({}, {_id: 0}).sort({x: 1}).toArray();
|
|
assertDocsInsertedCorrectly(res, pipeline);
|
|
assertFn(res);
|
|
}
|
|
|
|
{ // Tests $merge with non-empty pipeline along with let in whenMatched spec.
|
|
const pipeline = [
|
|
documentsStage,
|
|
{
|
|
$merge: {
|
|
into: outCollName,
|
|
let : {num: 123},
|
|
whenMatched: [{$set: {number: "$$num"}}],
|
|
on: "x"
|
|
}
|
|
}
|
|
];
|
|
|
|
testFn(pipeline, res => {
|
|
assert.eq(res.filter(elem => elem.number === 123).length, 1);
|
|
});
|
|
}
|
|
|
|
{ // Tests $merge with non-empty pipeline in whenMatched spec.
|
|
const pipeline = [
|
|
documentsStage,
|
|
{$merge: {into: outCollName, whenMatched: [{$set: {new: true}}], on: "x"}}
|
|
];
|
|
|
|
testFn(pipeline, res => {
|
|
assert.eq(res.filter(elem => elem.new === true).length, 1);
|
|
});
|
|
}
|
|
|
|
// Tests each combination of merge modes.
|
|
withEachMergeMode(({whenMatchedMode, whenNotMatchedMode}) => {
|
|
const expectErrorCode = whenMatchedMode === "fail"
|
|
? ErrorCodes.DuplicateKey
|
|
: whenNotMatchedMode === "fail" ? ErrorCodes.MergeStageNoMatchingDocument : null;
|
|
|
|
// Creates an index as $merge requires a unique index with the 'on' identifier field. Then
|
|
// inserts a document allowed to be matched.
|
|
dropWithoutImplicitRecreate(outCollName);
|
|
assert.commandWorked(outColl.createIndex({x: 1}, {unique: true}));
|
|
assert.commandWorked(outColl.insert({x: 10, old: true}));
|
|
|
|
const pipeline = [
|
|
documentsStage,
|
|
{
|
|
$merge: {
|
|
into: outCollName,
|
|
whenMatched: whenMatchedMode,
|
|
whenNotMatched: whenNotMatchedMode,
|
|
on: "x",
|
|
}
|
|
}
|
|
];
|
|
|
|
if (expectErrorCode) {
|
|
assert.throwsWithCode(() => db.aggregate(pipeline), expectErrorCode);
|
|
return;
|
|
}
|
|
|
|
assert.doesNotThrow(() => db.aggregate(pipeline));
|
|
let res = outColl.find({}, {_id: 0}).sort({x: 1}).toArray();
|
|
if (whenNotMatchedMode == "discard") {
|
|
assert.eq(outColl.count(), 1);
|
|
} else {
|
|
assertDocsInsertedCorrectly(res, pipeline);
|
|
}
|
|
|
|
// Asserts if the old document is replaced when 'whenMatchedMode' is "replace".
|
|
assert.eq(res.filter(elem => elem.old === true).length, whenMatchedMode == "replace" ? 0 : 1);
|
|
});
|