diff options
author | Bernard Gorman <bernard.gorman@gmail.com> | 2018-11-22 11:54:11 +0000 |
---|---|---|
committer | Bernard Gorman <bernard.gorman@gmail.com> | 2018-12-06 03:13:36 +0000 |
commit | 66316884a4b1180a8cceb6381e3c51e56586fc3e (patch) | |
tree | 1feed0db1f7f5fbc8368bb08d5607b9f3880597e /jstests/core | |
parent | 320e3b4aca116b1384a94057a0632d759d8f6cef (diff) | |
download | mongo-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.js | 45 |
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}]); + } }()); |