diff options
author | Ted Tuckman <ted.tuckman@mongodb.com> | 2020-06-09 10:08:29 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-03 15:39:37 +0000 |
commit | 1be4f1b11d932a7799a6b08385c650bb61867e50 (patch) | |
tree | 4f0ffd0f6a98027cb8d1927cf8bf1f3637776722 /jstests | |
parent | 13a49321277a5b9fcc180594964a801b9136f6f2 (diff) | |
download | mongo-1be4f1b11d932a7799a6b08385c650bb61867e50.tar.gz |
SERVER-47382 Support inequalities on arrays with $not on indexed collection
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/aggregation/extras/utils.js | 37 | ||||
-rw-r--r-- | jstests/core/array_index_and_nonIndex_consistent.js | 79 |
2 files changed, 94 insertions, 22 deletions
diff --git a/jstests/aggregation/extras/utils.js b/jstests/aggregation/extras/utils.js index 1d5f5dee228..088ffa786e7 100644 --- a/jstests/aggregation/extras/utils.js +++ b/jstests/aggregation/extras/utils.js @@ -174,6 +174,43 @@ function arrayEq(al, ar, verbose = false, valueComparator, fieldsToSkip = []) { return true; } +function arrayDiff(al, ar, verbose = false, valueComparator) { + // Check that these are both arrays. + if (!(al instanceof Array)) { + debug('arrayDiff: al is not an array: ' + tojson(al)); + return false; + } + + if (!(ar instanceof Array)) { + debug('arrayDiff: ar is not an array: ' + tojson(ar)); + return false; + } + + // Keep a set of which indexes we've already used to avoid considering [1,1] as equal to [1,2]. + const matchedIndexesInRight = new Set(); + let unmatchedElementsInLeft = []; + for (let leftElem of al) { + let foundMatch = false; + for (let i = 0; i < ar.length; ++i) { + if (!matchedIndexesInRight.has(i) && anyEq(leftElem, ar[i], verbose, valueComparator)) { + matchedIndexesInRight.add(i); // Don't use the same value each time. + foundMatch = true; + break; + } + } + if (!foundMatch) { + unmatchedElementsInLeft.push(leftElem); + } + } + let unmatchedElementsInRight = []; + for (let i = 0; i < ar.length; ++i) { + if (!matchedIndexesInRight.has(i)) { + unmatchedElementsInRight.push(ar[i]); + } + } + return {left: unmatchedElementsInLeft, right: unmatchedElementsInRight}; +} + /** * Makes a shallow copy of 'a'. */ diff --git a/jstests/core/array_index_and_nonIndex_consistent.js b/jstests/core/array_index_and_nonIndex_consistent.js index 7846032c21a..71657238d91 100644 --- a/jstests/core/array_index_and_nonIndex_consistent.js +++ b/jstests/core/array_index_and_nonIndex_consistent.js @@ -2,6 +2,7 @@ * Make sure that $gt and $lt queries return the same results regardless of whether there is a * multikey index. * @tags: [ + * requires_fcv_47, * sbe_incompatible, * ] */ @@ -9,6 +10,18 @@ (function() { "use strict"; load("jstests/aggregation/extras/utils.js"); // arrayEq + +function buildErrorString(q, indexed, nonIndexed) { + const arrDiff = arrayDiff(indexed, nonIndexed); + if (arrDiff === false) { + return ""; + } + let errStr = "Ran query " + tojson(q) + + " and got mismatched results.\nUnmatched from indexed collection (" + arrDiff.left.length + + "/" + indexed.length + "): " + tojson(arrDiff.left) + "\nUnmatched from nonIndexed (" + + arrDiff.right.length + "/" + nonIndexed.length + "): " + tojson(arrDiff.right); + return errStr; +} const indexColl = db.indexColl; const nonIndexedColl = db.nonIndexedColl; indexColl.drop(); @@ -35,6 +48,8 @@ collList.forEach(function(collObj) { {val: [true, 1]}, {val: [1, 4]}, {val: [null]}, + // TODO SERVER-49766 Enable this test once the bug is found and fixed. + // {val: null}, {val: MinKey}, {val: [MinKey]}, {val: [MinKey, 3]}, @@ -48,31 +63,51 @@ collList.forEach(function(collObj) { }); const queryList = [ - [2, 2], [0, 3], [3, 0], [1, 3], [3, 1], [1, 5], [5, 1], [1], - [3], [5], {"test": 2}, {"test": 6}, [true, true], [true], true, 1, - 3, 5, null, [null], [], [MinKey], [MinKey, 2], [MinKey, 4], - MinKey, [MaxKey], [MaxKey, 2], [MaxKey, 4], MaxKey, [], + [2, 2], [0, 3], [3, 0], [1, 3], [3, 1], [1, 5], [5, 1], [1], + [3], [5], {"test": 2}, {"test": 6}, [true, true], [true], true, 1, + 3, 5, [], [MinKey], [MinKey, 2], [MinKey, 4], MinKey, [MaxKey], + [MaxKey, 2], [MaxKey, 4], MaxKey, [], false, + // TODO: SERVER-49766 Enable these queries. + // null, [null], ]; -let failedLT = []; -let failedGT = []; - queryList.forEach(function(q) { - const queryLT = {val: {"$lt": q}}; - const queryGT = {val: {"$gt": q}}; + const queryPreds = [ + {$lt: q}, + {$lte: q}, + {$gt: q}, + {$gte: q}, + {$eq: q}, + {$not: {$lt: q}}, + {$not: {$lte: q}}, + {$not: {$gt: q}}, + {$not: {$gte: q}}, + {$not: {$eq: q}}, + ]; const projOutId = {_id: 0, val: 1}; - - let indexRes = indexColl.find(queryLT, projOutId).sort({val: 1}).toArray(); - let nonIndexedRes = nonIndexedColl.find(queryLT, projOutId).sort({val: 1}).toArray(); - - assert(arrayEq(indexRes, nonIndexedRes), - "Ran query " + tojson(queryLT) + " and got mismatched results.\n Indexed: " + - tojson(indexRes) + "\n NonIndexed: " + tojson(nonIndexedRes)); - - indexRes = indexColl.find(queryGT, projOutId).sort({val: 1}).toArray(); - nonIndexedRes = nonIndexedColl.find(queryGT, projOutId).sort({val: 1}).toArray(); - assert(arrayEq(indexRes, nonIndexedRes), - "Ran query " + tojson(queryGT) + " and got mismatched results.\n Indexed: " + - tojson(indexRes) + "\n NonIndexed: " + tojson(nonIndexedRes)); + queryPreds.forEach(function(pred) { + const query = {val: pred}; + const indexRes = indexColl.find(query, projOutId).sort({val: 1}).toArray(); + const nonIndexedRes = nonIndexedColl.find(query, projOutId).sort({val: 1}).toArray(); + assert(arrayEq(indexRes, nonIndexedRes), buildErrorString(query, indexRes, nonIndexedRes)); + }); +}); +// Test queries with multiple intervals. +const multiIntQueryList = [ + {val: {$gt: 1, $lt: 3}}, + {val: {$gt: [1], $lt: [3]}}, + {val: {$not: {$gt: 3, $lt: 1}}}, + {val: {$not: {$gt: [3], $lt: [1]}}}, + {val: {$not: {$gt: [3], $lt: 1}}}, + {val: {$not: {$not: {$lt: 3}}}}, + {val: {$not: {$not: {$lt: true}}}}, + {val: {$not: {$not: {$lt: [true]}}}}, + {val: {$not: {$not: {$lt: [3]}}}}, +]; +multiIntQueryList.forEach(function(q) { + const projOutId = {_id: 0, val: 1}; + const indexRes = indexColl.find(q, projOutId).sort({val: 1}).toArray(); + const nonIndexedRes = nonIndexedColl.find(q, projOutId).sort({val: 1}).toArray(); + assert(arrayEq(indexRes, nonIndexedRes), buildErrorString(q, indexRes, nonIndexedRes)); }); })(); |