summaryrefslogtreecommitdiff
path: root/jstests/core
diff options
context:
space:
mode:
authorBernard Gorman <bernard.gorman@gmail.com>2018-11-22 11:54:11 +0000
committerBernard Gorman <bernard.gorman@gmail.com>2018-12-06 03:13:36 +0000
commit66316884a4b1180a8cceb6381e3c51e56586fc3e (patch)
tree1feed0db1f7f5fbc8368bb08d5607b9f3880597e /jstests/core
parent320e3b4aca116b1384a94057a0632d759d8f6cef (diff)
downloadmongo-66316884a4b1180a8cceb6381e3c51e56586fc3e.tar.gz
SERVER-38164 $or pushdown optimization does not correctly handle $not within an $elemMatch
(cherry picked from commit 94d0e046baa64d1aa1a6af97e2d19bb466cc1ff5)
Diffstat (limited to 'jstests/core')
-rw-r--r--jstests/core/elemmatch_or_pushdown.js45
1 files changed, 44 insertions, 1 deletions
diff --git a/jstests/core/elemmatch_or_pushdown.js b/jstests/core/elemmatch_or_pushdown.js
index f1a1dacd7ad..b33afcc23b8 100644
--- a/jstests/core/elemmatch_or_pushdown.js
+++ b/jstests/core/elemmatch_or_pushdown.js
@@ -1,5 +1,6 @@
/**
- * Tests that an $elemMatch-$or query is evaluated correctly. Designed to reproduce SERVER-33005.
+ * Tests that an $elemMatch-$or query is evaluated correctly. Designed to reproduce SERVER-33005 and
+ * SERVER-38164.
*/
(function() {
"use strict";
@@ -38,4 +39,46 @@
.sort({_id: 1})
.toArray(),
[{_id: 0, a: 5, b: [{c: [{f: 8}], d: 6}]}, {_id: 4, a: 5, b: [{c: [{f: 8}], e: 7}]}]);
+
+ // Test that $not predicates in $elemMatch can be pushed into an $or sibling of the $elemMatch.
+ coll.drop();
+ assert.writeOK(coll.insert({_id: 0, arr: [{a: 0, b: 2}], c: 4, d: 5}));
+ assert.writeOK(coll.insert({_id: 1, arr: [{a: 1, b: 2}], c: 4, d: 5}));
+ assert.writeOK(coll.insert({_id: 2, arr: [{a: 0, b: 3}], c: 4, d: 5}));
+ assert.writeOK(coll.insert({_id: 3, arr: [{a: 1, b: 3}], c: 4, d: 5}));
+ assert.writeOK(coll.insert({_id: 4, arr: [{a: 0, b: 2}], c: 6, d: 7}));
+ assert.writeOK(coll.insert({_id: 5, arr: [{a: 1, b: 2}], c: 6, d: 7}));
+ assert.writeOK(coll.insert({_id: 6, arr: [{a: 0, b: 3}], c: 6, d: 7}));
+ assert.writeOK(coll.insert({_id: 7, arr: [{a: 1, b: 3}], c: 6, d: 7}));
+
+ const keyPattern = {"arr.a": 1, "arr.b": 1, c: 1, d: 1};
+ assert.commandWorked(coll.createIndex(keyPattern));
+
+ const elemMatchOr = {
+ arr: {$elemMatch: {a: {$ne: 1}, $or: [{b: 2}, {b: 3}]}},
+ $or: [
+ {c: 4, d: 5},
+ {c: 6, d: 7},
+ ],
+ };
+
+ // Confirm that we get the same results using the index and a COLLSCAN.
+ for (let hint of[keyPattern, {$natural: 1}]) {
+ assert.eq(coll.find(elemMatchOr, {_id: 1}).sort({_id: 1}).hint(hint).toArray(),
+ [{_id: 0}, {_id: 2}, {_id: 4}, {_id: 6}]);
+
+ assert.eq(
+ coll.aggregate(
+ [
+ {
+ $match:
+ {arr: {$elemMatch: {a: {$ne: 1}}}, $or: [{c: 4, d: 5}, {c: 6, d: 7}]}
+ },
+ {$project: {_id: 1}},
+ {$sort: {_id: 1}}
+ ],
+ {hint: hint})
+ .toArray(),
+ [{_id: 0}, {_id: 2}, {_id: 4}, {_id: 6}]);
+ }
}());