summaryrefslogtreecommitdiff
path: root/jstests/core
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2018-02-08 14:55:41 -0500
committerDavid Storch <david.storch@10gen.com>2018-02-12 12:14:21 -0500
commit228a8e7d410ae01dc2ee8b90a83ddf08aa219bc9 (patch)
treebb24e97a3e14e8466088a9a1e588cd75e7187cda /jstests/core
parent5ccb16c2b8eb80d1eb3fe4e6ba36c092e03eb5d4 (diff)
downloadmongo-228a8e7d410ae01dc2ee8b90a83ddf08aa219bc9.tar.gz
SERVER-33005 Fix planner to avoid incorrect OR pushdown through $elemMatch.
The PlanEnumerator now tracks pushdown routes which descend through an $elemMatch object. These routes are pruned when subsequently descending through an OR. (cherry picked from commit 17b4094c4d781ffd486b27869f46eea706e490af)
Diffstat (limited to 'jstests/core')
-rw-r--r--jstests/core/elemmatch_or_pushdown.js41
1 files changed, 41 insertions, 0 deletions
diff --git a/jstests/core/elemmatch_or_pushdown.js b/jstests/core/elemmatch_or_pushdown.js
new file mode 100644
index 00000000000..f1a1dacd7ad
--- /dev/null
+++ b/jstests/core/elemmatch_or_pushdown.js
@@ -0,0 +1,41 @@
+/**
+ * Tests that an $elemMatch-$or query is evaluated correctly. Designed to reproduce SERVER-33005.
+ */
+(function() {
+ "use strict";
+
+ const coll = db.elemmatch_or_pushdown;
+ coll.drop();
+
+ assert.writeOK(coll.insert({_id: 0, a: 1, b: [{c: 4}]}));
+ assert.writeOK(coll.insert({_id: 1, a: 2, b: [{c: 4}]}));
+ assert.writeOK(coll.insert({_id: 2, a: 2, b: [{c: 5}]}));
+ assert.writeOK(coll.insert({_id: 3, a: 1, b: [{c: 5}]}));
+ assert.writeOK(coll.insert({_id: 4, a: 1, b: [{c: 6}]}));
+ assert.writeOK(coll.insert({_id: 5, a: 1, b: [{c: 7}]}));
+ assert.commandWorked(coll.createIndex({a: 1, "b.c": 1}));
+
+ assert.eq(coll.find({a: 1, b: {$elemMatch: {$or: [{c: 4}, {c: 5}]}}}).sort({_id: 1}).toArray(),
+ [{_id: 0, a: 1, b: [{c: 4}]}, {_id: 3, a: 1, b: [{c: 5}]}]);
+ assert.eq(coll.find({a: 1, $or: [{a: 2}, {b: {$elemMatch: {$or: [{c: 4}, {c: 5}]}}}]})
+ .sort({_id: 1})
+ .toArray(),
+ [{_id: 0, a: 1, b: [{c: 4}]}, {_id: 3, a: 1, b: [{c: 5}]}]);
+
+ coll.drop();
+ assert.writeOK(coll.insert({_id: 0, a: 5, b: [{c: [{f: 8}], d: 6}]}));
+ assert.writeOK(coll.insert({_id: 1, a: 4, b: [{c: [{f: 8}], d: 6}]}));
+ assert.writeOK(coll.insert({_id: 2, a: 5, b: [{c: [{f: 8}], d: 7}]}));
+ assert.writeOK(coll.insert({_id: 3, a: 4, b: [{c: [{f: 9}], d: 6}]}));
+ assert.writeOK(coll.insert({_id: 4, a: 5, b: [{c: [{f: 8}], e: 7}]}));
+ assert.writeOK(coll.insert({_id: 5, a: 4, b: [{c: [{f: 8}], e: 7}]}));
+ assert.writeOK(coll.insert({_id: 6, a: 5, b: [{c: [{f: 8}], e: 8}]}));
+ assert.writeOK(coll.insert({_id: 7, a: 5, b: [{c: [{f: 9}], e: 7}]}));
+ assert.commandWorked(coll.createIndex({"b.d": 1, "b.c.f": 1}));
+ assert.commandWorked(coll.createIndex({"b.e": 1, "b.c.f": 1}));
+
+ assert.eq(coll.find({a: 5, b: {$elemMatch: {c: {$elemMatch: {f: 8}}, $or: [{d: 6}, {e: 7}]}}})
+ .sort({_id: 1})
+ .toArray(),
+ [{_id: 0, a: 5, b: [{c: [{f: 8}], d: 6}]}, {_id: 4, a: 5, b: [{c: [{f: 8}], e: 7}]}]);
+}());