summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
Diffstat (limited to 'jstests')
-rw-r--r--jstests/core/index_id_options.js26
-rw-r--r--jstests/core/index_partial_create_drop.js22
-rw-r--r--jstests/core/index_partial_read_ops.js77
-rw-r--r--jstests/core/index_partial_write_ops.js5
-rw-r--r--jstests/noPassthrough/index_partial_no_explain_cmds.js29
-rw-r--r--jstests/noPassthrough/index_partial_no_hint_cmds.js59
6 files changed, 131 insertions, 87 deletions
diff --git a/jstests/core/index_id_options.js b/jstests/core/index_id_options.js
index 91e57b73dc6..5333c12daa8 100644
--- a/jstests/core/index_id_options.js
+++ b/jstests/core/index_id_options.js
@@ -1,11 +1,12 @@
// Test creation of the _id index with various options:
// - _id indexes must be unique.
// - _id indexes can't be sparse.
+// - _id indexes can't be partial indexes.
var coll = db.index_id_options;
//
-// Uniqueness.
+// Unique index.
//
// Creation of _id index with "non-zero" value for "unique" should succeed.
@@ -31,7 +32,7 @@ assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
assert.commandFailed(coll.ensureIndex({_id: 1}, {unique: NumberLong(0)}));
//
-// Sparseness.
+// Sparse index.
//
// Creation of _id index with "non-zero" value for "sparse" should fail.
@@ -55,3 +56,24 @@ assert.commandWorked(coll.ensureIndex({_id: 1}, {sparse: 0}));
coll.drop();
assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
assert.commandWorked(coll.ensureIndex({_id: 1}, {sparse: NumberLong(0)}));
+
+//
+// Partial index.
+//
+
+// Creation of _id index with any value for "partialFilterExpression" should fail.
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: false}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: null}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: {}}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: {a: 1}}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: []}));
diff --git a/jstests/core/index_partial_create_drop.js b/jstests/core/index_partial_create_drop.js
index 4f9f9c514eb..d997f0fcfa3 100644
--- a/jstests/core/index_partial_create_drop.js
+++ b/jstests/core/index_partial_create_drop.js
@@ -5,7 +5,7 @@
var isMongos = (db.runCommand("isMaster").msg === "isdbgrid");
var coll = db.index_partial_create_drop;
- var getNumKeys = function(idxName) {
+ var getNumKeys = function (idxName) {
var res = assert.commandWorked(coll.validate(true));
var kpi;
if (isMongos) {
@@ -19,7 +19,7 @@
coll.drop();
- // Check bad partialFilterExpression spec on create.
+ // Check bad filter spec on create.
assert.commandFailed(coll.ensureIndex({x: 1}, {partialFilterExpression: 5}));
assert.commandFailed(coll.ensureIndex({x: 1}, {partialFilterExpression: {x: {$asdasd: 3}}}));
assert.commandFailed(coll.ensureIndex({x: 1}, {partialFilterExpression: {$and: 5}}));
@@ -40,7 +40,8 @@
assert.eq(1, coll.getIndexes().length);
// Create partial index in background.
- assert.commandWorked(coll.ensureIndex({x: 1}, {background: true, partialFilterExpression: {a: {$lt: 5}}}));
+ assert.commandWorked(coll.ensureIndex({x: 1}, {background: true,
+ partialFilterExpression: {a: {$lt: 5}}}));
assert.eq(5, getNumKeys("x_1"));
assert.commandWorked(coll.dropIndex({x: 1}));
assert.eq(1, coll.getIndexes().length);
@@ -54,15 +55,14 @@
// Partial indexes can't also be sparse indexes.
assert.commandFailed(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}, sparse: true}));
assert.commandFailed(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}, sparse: 1}));
- assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}, sparse: false}));
+ assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1},
+ sparse: false}));
assert.eq(2, coll.getIndexes().length);
assert.commandWorked(coll.dropIndex({x: 1}));
+ assert.eq(1, coll.getIndexes().length);
- // _id index can't be a partial index. SERVER-18170
- //coll.drop();
- //assert.commandWorked(db.createCollection("index_partial_basic",
- // {autoIndexId: false}));
- //assert.commandFailed(coll.ensureIndex({_id: 1}, {partialFilterExpression: {a: 1}}));
-
+ // SERVER-18858: Verify that query compatible w/ partial index succeeds after index drop.
+ assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: {$lt: 5}}}));
+ assert.commandWorked(coll.dropIndex({x: 1}));
+ assert.eq(1, coll.find({x: 0, a: 0}).itcount());
})();
-
diff --git a/jstests/core/index_partial_read_ops.js b/jstests/core/index_partial_read_ops.js
index 40005d510dc..ef5c30d25a6 100644
--- a/jstests/core/index_partial_read_ops.js
+++ b/jstests/core/index_partial_read_ops.js
@@ -1,25 +1,78 @@
// Read ops tests for partial indexes.
+// Include helpers for analyzing explain output.
+load("jstests/libs/analyze_plan.js");
+
(function() {
"use strict";
- var ret;
+ var explain;
var coll = db.index_partial_read_ops;
coll.drop();
- coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}});
+ assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: {$lte: 1.5}}}));
assert.writeOK(coll.insert({x: 5, a: 2})); // Not in index.
assert.writeOK(coll.insert({x: 6, a: 1})); // In index.
- // Verify index counts and basic functionality.
- assert.eq(1, coll.find({x: 6}).itcount());
- assert.eq(1, coll.find({x: 6, a: 1}).hint({x: 1}).itcount());
- assert.eq(1, coll.find({x: {$gt: 1}, a: 1}).hint({x: 1}).itcount());
- // Hint is bad because a < 5 is not a subset of a = 1
- assert.throws(function() {
- coll.find({x: 6, a: {$lt: 5}}).hint({x: 1}).itcount()
- });
+ //
+ // Verify basic functionality with find().
+ //
+
+ // find() operations that should use index.
+ explain = coll.explain('executionStats').find({x: 6, a: 1}).finish();
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+ explain = coll.explain('executionStats').find({x: {$gt: 1}, a: 1}).finish();
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+ explain = coll.explain('executionStats').find({x: 6, a: {$lte: 1}}).finish();
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+
+ // find() operations that should not use index.
+ explain = coll.explain('executionStats').find({x: 6, a: {$lt: 1.6}}).finish();
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isCollscan(explain.queryPlanner.winningPlan));
+ explain = coll.explain('executionStats').find({x: 6}).finish();
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isCollscan(explain.queryPlanner.winningPlan));
+
+ //
+ // Verify basic functionality with the count command.
+ //
+
+ // Count operation that should use index.
+ explain = coll.explain('executionStats').count({x: {$gt: 1}, a: 1});
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+
+ // Count operation that should not use index.
+ explain = coll.explain('executionStats').count({x: {$gt: 1}, a: 2});
+ assert(isCollscan(explain.queryPlanner.winningPlan));
+
+ //
+ // Verify basic functionality with the aggregate command.
+ //
+
+ // Aggregate operation that should use index.
+ explain = coll.aggregate([{$match: {x: {$gt: 1}, a: 1}}], {explain: true}).stages[0].$cursor;
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+
+ // Aggregate operation that should not use index.
+ explain = coll.aggregate([{$match: {x: {$gt: 1}, a: 2}}], {explain: true}).stages[0].$cursor;
+ assert(isCollscan(explain.queryPlanner.winningPlan));
+
+ //
+ // Verify basic functionality with the findAndModify command.
+ //
- // Count has special query path
- assert.eq(1, coll.find({x: {$gt: 1}, a: 1}).hint({x: 1}).count());
+ // findAndModify operation that should use index.
+ explain = coll.explain('executionStats').findAndModify({query: {x: {$gt: 1}, a: 1},
+ update: {$inc: {x: 1}}});
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isIxscan(explain.queryPlanner.winningPlan));
+ // findAndModify operation that should not use index.
+ explain = coll.explain('executionStats').findAndModify({query: {x: {$gt: 1}, a: 2},
+ update: {$inc: {x: 1}}});
+ assert.eq(1, explain.executionStats.nReturned);
+ assert(isCollscan(explain.queryPlanner.winningPlan));
})();
diff --git a/jstests/core/index_partial_write_ops.js b/jstests/core/index_partial_write_ops.js
index 6ddc4c9afa6..92d3720d07e 100644
--- a/jstests/core/index_partial_write_ops.js
+++ b/jstests/core/index_partial_write_ops.js
@@ -1,11 +1,11 @@
-// Write ops tests for partial indexes
+// Write ops tests for partial indexes.
(function() {
"use strict";
var isMongos = (db.runCommand("isMaster").msg === "isdbgrid");
var coll = db.index_partial_write_ops;
- var getNumKeys = function(idxName) {
+ var getNumKeys = function (idxName) {
var res = assert.commandWorked(coll.validate(true));
var kpi;
if (isMongos) {
@@ -60,5 +60,4 @@
// Delete that does affect partial index.
assert.writeOK(coll.remove({x: 6}));
assert.eq(0, getNumKeys("x_1"));
-
})();
diff --git a/jstests/noPassthrough/index_partial_no_explain_cmds.js b/jstests/noPassthrough/index_partial_no_explain_cmds.js
new file mode 100644
index 00000000000..9ea81569d4d
--- /dev/null
+++ b/jstests/noPassthrough/index_partial_no_explain_cmds.js
@@ -0,0 +1,29 @@
+// Test partial indexes with commands that don't use explain. These commands are tested against
+// mongod with the --notablescan flag set, so that they fail if the index is not used.
+(function() {
+ "use strict";
+ var runner = MongoRunner.runMongod({setParameter: "notablescan=1"});
+ var coll = runner.getDB("test").index_partial_no_explain_cmds;
+ var ret;
+
+ coll.drop();
+
+ assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}}));
+
+ assert.writeOK(coll.insert({_id: 1, x: 5, a: 2})); // Not in index.
+ assert.writeOK(coll.insert({_id: 2, x: 6, a: 1})); // In index.
+
+ // Verify we will throw if the partial index can't be used.
+ assert.throws(function() { coll.find({x: {$gt: 1}, a: 2}).itcount(); });
+
+ // Test mapReduce.
+ var mapFunc = function() { emit(this._id, 1); };
+ var reduceFunc = function (keyId, countArray) { return Array.sum(countArray); };
+
+ ret = coll.mapReduce(mapFunc, reduceFunc, {out: "inline", query: {x: {$gt: 1}, a: 1}});
+ assert.eq(1, ret.counts.input);
+
+ // Test distinct.
+ ret = coll.distinct("a", {x: {$gt: 1}, a: 1});
+ assert.eq(1, ret.length);
+})();
diff --git a/jstests/noPassthrough/index_partial_no_hint_cmds.js b/jstests/noPassthrough/index_partial_no_hint_cmds.js
deleted file mode 100644
index eb126432dd9..00000000000
--- a/jstests/noPassthrough/index_partial_no_hint_cmds.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Test partial indexes with commands that won't test well
-// under sharding passthrough
-(function () {
- "use strict";
- // Launch mongod with notable scan, since these tests are
- // centered around operations that can't take a hint.
- var runner = MongoRunner.runMongod({setParameter: "notablescan=1"});
- var coll = runner.getDB("test").index_partial_no_hint_cmds;
- var ret;
-
- var getNumKeys = function(idxName) {
- var res = assert.commandWorked(coll.validate(true));
- return res.keysPerIndex[coll.getFullName() + ".$" + idxName];
- };
-
- coll.drop();
-
- assert.commandWorked(coll.ensureIndex({x: 1}, {partialFilterExpression: {a: 1}}));
-
- assert.writeOK(coll.insert({_id: 1, x: 5, a: 2})); // Not in index.
- assert.writeOK(coll.insert({_id: 2, x: 6, a: 1})); // In index.
-
- // Verify we will throw if the partial index isn't used. Find won't
- // necessarily assert in this case, but findAndModify does consistenly.
- assert.throws(function() {
- coll.findAndModify({query: {x: {$gt: 1}, a: 2}, update: {$inc: {x: 1}}, new: true})
- });
-
- // Verify mapReduce is using the partial index.
- var mapFunc = function () { emit(this._id, 1); };
- var reduceFunc = function (keyId, countArray) { return Array.sum(countArray); };
-
- ret = coll.mapReduce(mapFunc, reduceFunc, {out: "inline", query: {x: {$gt: 1}, a: 1}});
- assert.eq(1, ret.counts.input);
-
- // Distinct and count have special query paths, but can't take hint.
- ret = coll.distinct("a", {x: {$gt: 1}, a: 1});
- assert.eq(1, ret.length);
-
- ret = coll.count({x: {$gt: 1}, a: 1});
- assert.eq(1, ret);
-
- // Verify findAndModify uses the partial index.
- ret = coll.findAndModify({query: {x: {$gt: 1}, a: 1},
- update: {$inc: {x: 1}}, new: true});
- assert.eq(2, ret._id);
- assert.eq(1, getNumKeys("x_1"));
-
-
- ret = coll.findAndModify({query:{x:{$gt:6}, a: 1},
- update: {$inc: {x: 1}}, new: true});
- assert.eq(2, ret._id);
- assert.eq(1, getNumKeys("x_1"));
-
- // Check that aggregate is using the partial index.
- ret = coll.aggregate([{$match: {x: {$gt: 1}, a: 1}},
- {$group: {_id:1, count: {$sum: 1}}}]).next();
- assert.eq(1, ret.count);
-})();