summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorTed Tuckman <ted.tuckman@mongodb.com>2020-01-24 15:53:43 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-15 16:07:47 +0000
commit1f89ab198058cd5ed012acd2b081f0e8c6949927 (patch)
tree6616c7810c4a822e73c4bc6721543cccf7d35212 /jstests
parentfc829bb485654a6325f358b2642aab34a9bc2543 (diff)
downloadmongo-1f89ab198058cd5ed012acd2b081f0e8c6949927.tar.gz
SERVER-45233 Indexed array inequality fixed to use correct bounds
create mode 100644 jstests/core/array_comparison_correctness.js create mode 100644 jstests/core/array_index_and_nonIndex_consistent.js (cherry picked from commit 52e7950cae37ef3783b05840c04abbbe383fa1ff)
Diffstat (limited to 'jstests')
-rw-r--r--jstests/core/array_comparison_correctness.js118
-rw-r--r--jstests/core/array_index_and_nonIndex_consistent.js74
-rw-r--r--jstests/core/array_match4.js5
3 files changed, 194 insertions, 3 deletions
diff --git a/jstests/core/array_comparison_correctness.js b/jstests/core/array_comparison_correctness.js
new file mode 100644
index 00000000000..5001d30a9a7
--- /dev/null
+++ b/jstests/core/array_comparison_correctness.js
@@ -0,0 +1,118 @@
+/*
+ * Demonstrate the expected behavior of $lt and $gt comparisons involving arrays. This is only
+ * tested without an index, results between index and non-index behavior are compared in
+ * array_index_and_nonIndex_consistent.js
+ */
+
+(function() {
+"use strict";
+load("jstests/aggregation/extras/utils.js"); // arrayEq
+const collName = jsTestName();
+const coll = db.getCollection(collName);
+coll.drop();
+const docsInColl = [
+ {_id: 0, val: [1, 2]},
+ {_id: 1, val: [3, 4]},
+ {_id: 2, val: [3, 1]},
+ {_id: 3, val: {"test": 5}},
+ {_id: 4, val: [{"test": 7}]},
+ {_id: 5, val: [true, false]},
+ {_id: 6, val: 2},
+ {_id: 7, val: 3},
+ {_id: 8, val: 4},
+ {_id: 9, val: [2]},
+ {_id: 10, val: [3]},
+ {_id: 11, val: [4]},
+ {_id: 12, val: [1, true]},
+ {_id: 13, val: [true, 1]},
+ {_id: 14, val: [1, 4]},
+ {_id: 15, val: [null]},
+ {_id: 16, val: MinKey},
+ {_id: 17, val: [MinKey]},
+ {_id: 18, val: [MinKey, 3]},
+ {_id: 19, val: [3, MinKey]},
+ {_id: 20, val: MaxKey},
+ {_id: 21, val: [MaxKey]},
+ {_id: 22, val: [MaxKey, 3]},
+ {_id: 23, val: [3, MaxKey]},
+ {_id: 24, val: true},
+ {_id: 25, val: false},
+];
+assert.commandWorked(coll.insert(docsInColl));
+function generateFailedEqString(expected, found) {
+ return "Expected: " + tojson(expected) + "\n Found: " + tojson(found);
+}
+function generateExpectedResults(indexes) {
+ resultSet = [];
+ indexes.forEach(function(index) {
+ resultSet.push(docsInColl[index]);
+ });
+ return resultSet;
+}
+// Querying for LT/GT an integer returns all arrays that have a single integer element that
+// matches the query.
+let resultSet = coll.find({val: {$lt: 2}}).toArray();
+let expected = generateExpectedResults([0, 2, 12, 14]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$gt: 2}}).toArray();
+expected = generateExpectedResults([1, 2, 8, 14]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+// Test that querying for GT MinKey and LT MaxKey returns all results except for those values.
+resultSet = coll.find({val: {$gt: MinKey}}).toArray();
+let expectedInts = [...Array(25).keys()];
+expectedInts.splice(16, 1);
+expected = generateExpectedResults(expectedInts);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$lt: MaxKey}}).toArray();
+expectedInts = [...Array(25).keys()];
+expectedInts.splice(20, 1);
+expected = generateExpectedResults(expectedInts);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+// Test that querying for GT [MinKey] or LT [MaxKey] returns all other arrays, but nothing else.
+resultSet = coll.find({val: {$gt: [MinKey]}}).toArray();
+expected = generateExpectedResults([0, 1, 2, 4, 5, 9, 10, 11, 12, 13, 14, 15, 18, 19, 21, 22, 23]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$lt: [MaxKey]}}).toArray();
+expected = generateExpectedResults([0, 1, 2, 4, 5, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 22, 23]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+// Test that querying for LT/GT true returns no other types.
+resultSet = coll.find({val: {$gt: true}}).toArray();
+expected = [];
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$lt: true}}).toArray();
+expected = generateExpectedResults([25]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+// Test that querying for LT/GT arrays maintains lexicographic (version number) order and only
+// returns arrays.
+resultSet = coll.find({val: {$lt: [-1]}}).toArray();
+expected = generateExpectedResults([15, 17, 18]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$lt: [3]}}).toArray();
+expected = generateExpectedResults([0, 9, 12, 14, 15, 17, 18]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$lt: [3, 2]}}).toArray();
+expected = generateExpectedResults([0, 2, 9, 12, 14, 15, 17, 18]);
+assert(arrayEq(resultSet, expected), (resultSet, expected));
+
+resultSet = coll.find({val: {$gt: [2]}}).toArray();
+expected = generateExpectedResults([1, 2, 4, 5, 10, 11, 13, 19, 21, 22]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$gt: [15]}}).toArray();
+expected = generateExpectedResults([5, 13, 21, 22]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+
+resultSet = coll.find({val: {$gt: [3, 3]}}).toArray();
+expected = generateExpectedResults([1, 4, 5, 11, 13, 19, 21, 22]);
+assert(arrayEq(resultSet, expected), generateFailedEqString(resultSet, expected));
+})();
diff --git a/jstests/core/array_index_and_nonIndex_consistent.js b/jstests/core/array_index_and_nonIndex_consistent.js
new file mode 100644
index 00000000000..5cba0e66a6a
--- /dev/null
+++ b/jstests/core/array_index_and_nonIndex_consistent.js
@@ -0,0 +1,74 @@
+/*
+ * Make sure that $gt and $lt queries return the same results regardless of whether there is a
+ * multikey index.
+ */
+
+(function() {
+"use strict";
+load("jstests/aggregation/extras/utils.js"); // arrayEq
+const indexColl = db.indexColl;
+const nonIndexedColl = db.nonIndexedColl;
+indexColl.drop();
+nonIndexedColl.drop();
+
+db.indexColl.createIndex({val: 1});
+const collList = [indexColl, nonIndexedColl];
+
+collList.forEach(function(collObj) {
+ assert.commandWorked(collObj.insert([
+ {val: [1, 2]},
+ {val: [3, 4]},
+ {val: [3, 1]},
+ {val: {"test": 5}},
+ {val: [{"test": 7}]},
+ {val: [true, false]},
+ {val: 2},
+ {val: 3},
+ {val: 4},
+ {val: [2]},
+ {val: [3]},
+ {val: [4]},
+ {val: [1, true]},
+ {val: [true, 1]},
+ {val: [1, 4]},
+ {val: [null]},
+ {val: MinKey},
+ {val: [MinKey]},
+ {val: [MinKey, 3]},
+ {val: [3, MinKey]},
+ {val: MaxKey},
+ {val: [MaxKey]},
+ {val: [MaxKey, 3]},
+ {val: [3, MaxKey]},
+ ]));
+});
+
+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,
+];
+
+let failedLT = [];
+let failedGT = [];
+
+queryList.forEach(function(q) {
+ const queryLT = {val: {"$lt": q}};
+ const queryGT = {val: {"$gt": 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));
+});
+})();
diff --git a/jstests/core/array_match4.js b/jstests/core/array_match4.js
index b4cdec5143a..dafbca8f4f9 100644
--- a/jstests/core/array_match4.js
+++ b/jstests/core/array_match4.js
@@ -1,3 +1,4 @@
+// @tags: [requires_fcv_44]
var t = db.array_match4;
t.drop();
@@ -25,6 +26,4 @@ print('explain for ' + tojson(query_gte, '', true) + ' = ' + tojson(explain));
// number of documents returned by indexes query should be consistent
// with non-indexed case.
-// XXX: The following assertion documents current behavior.
-// XXX: 2.4 and 2.6 both return 0 documents.
-assert.eq(0, t.find(query_gte).itcount(), '$gte (with index)');
+assert.eq(1, t.find(query_gte).itcount(), '$gte (with index)');