summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernard Gorman <bernard.gorman@gmail.com>2018-10-03 17:38:54 +0100
committerBernard Gorman <bernard.gorman@gmail.com>2018-10-03 22:36:02 +0100
commitb73a042894580032505768ea94c58348c5e4bc79 (patch)
tree1a09f75d0a9ab5336df587d1db2a71c02d383afb
parent3077fb640b0df0b8d769aafd0d38e67d3307198b (diff)
downloadmongo-b73a042894580032505768ea94c58348c5e4bc79.tar.gz
SERVER-36198 Remove 'internalQueryAllowAllPathsIndexes' server parameter
-rw-r--r--etc/perf.yml6
-rw-r--r--jstests/concurrency/fsm_workloads/create_index_background_wildcard.js11
-rw-r--r--jstests/concurrency/fsm_workloads/indexed_insert_wildcard.js11
-rw-r--r--jstests/concurrency/fsm_workloads/reindex.js21
-rw-r--r--jstests/libs/discover_topology.js30
-rw-r--r--jstests/multiVersion/wildcard_index_feature_compatability_version.js7
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_and_text_indexes.js88
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_basic_index_bounds.js48
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_cached_plans.js3
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_collation.js143
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_covered_queries.js82
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_empty_arrays.js63
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_equality_to_empty_obj.js97
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_filter.js71
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_hint.js161
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_minmax.js148
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_multikey.js283
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_nonblocking_sort.js4
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_partial_index.js18
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_return_key.js72
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_validindex.js252
-rw-r--r--src/mongo/db/catalog/index_key_validate.cpp7
-rw-r--r--src/mongo/db/catalog/index_key_validate_test.cpp5
-rw-r--r--src/mongo/db/catalog/index_spec_validate_test.cpp6
-rw-r--r--src/mongo/db/query/query_knobs.cpp2
-rw-r--r--src/mongo/db/query/query_knobs.h6
-rw-r--r--src/mongo/dbtests/validate_tests.cpp5
-rw-r--r--src/mongo/dbtests/wildcard_multikey_persistence_test.cpp3
28 files changed, 693 insertions, 960 deletions
diff --git a/etc/perf.yml b/etc/perf.yml
index aee01faf84f..0f9fdbb3a2e 100644
--- a/etc/perf.yml
+++ b/etc/perf.yml
@@ -526,8 +526,6 @@ buildvariants:
compile_flags: --ssl MONGO_DISTMOD=rhel62 -j$(grep -c ^processor /proc/cpuinfo) --release --variables-files=etc/scons/mongodbtoolchain_gcc.vars
mongod_exec_wrapper: &exec_wrapper "numactl --physcpubind=4,5,6,7 -i 1"
perf_exec_wrapper: &perf_wrapper "numactl --physcpubind=1,2,3 -i 0"
- # TODO SERVER-36198: Remove the `--setParameter internalQueryAllowAllPathsIndexes=true` line
- # when wildcard indexes are enabled by default.
mongod_flags: >-
--auth
--fork
@@ -537,7 +535,6 @@ buildvariants:
--networkMessageCompressors noop
--setParameter diagnosticDataCollectionEnabled=false
--setParameter enableTestCommands=1
- --setParameter internalQueryAllowAllPathsIndexes=true
--setParameter ttlMonitorEnabled=false
--storageEngine inMemory
--syncdelay 0
@@ -569,8 +566,6 @@ buildvariants:
expansions:
mongod_exec_wrapper: *exec_wrapper
perf_exec_wrapper: *perf_wrapper
- # TODO SERVER-36198: Remove the `--setParameter internalQueryAllowAllPathsIndexes=true` line
- # when wildcard indexes are enabled by default.
mongod_flags: >-
--auth
--fork
@@ -582,7 +577,6 @@ buildvariants:
--replSet test
--setParameter diagnosticDataCollectionEnabled=false
--setParameter enableTestCommands=1
- --setParameter internalQueryAllowAllPathsIndexes=true
--setParameter ttlMonitorEnabled=false
--storageEngine inMemory
--syncdelay 0
diff --git a/jstests/concurrency/fsm_workloads/create_index_background_wildcard.js b/jstests/concurrency/fsm_workloads/create_index_background_wildcard.js
index 631d5411fa3..5ad4f86e2d8 100644
--- a/jstests/concurrency/fsm_workloads/create_index_background_wildcard.js
+++ b/jstests/concurrency/fsm_workloads/create_index_background_wildcard.js
@@ -5,7 +5,6 @@
*/
load('jstests/concurrency/fsm_libs/extend_workload.js'); // For extendWorkload.
load('jstests/concurrency/fsm_workloads/create_index_background.js'); // For $config.
-load('jstests/libs/discover_topology.js'); // For findDataBearingNodes().
var $config = extendWorkload($config, function($config, $super) {
$config.data.getIndexSpec = function() {
@@ -25,16 +24,6 @@ var $config = extendWorkload($config, function($config, $super) {
};
$config.setup = function setup() {
- // Enable the test flag required in order to build $** indexes on all data bearing nodes.
- // TODO SERVER-36198: Remove this.
- const hosts = DiscoverTopology.findDataBearingNodes(db.getMongo());
- for (let host of hosts) {
- const conn = new Mongo(host);
- const adminDB = conn.getDB("admin");
- assert.commandWorked(
- adminDB.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- }
-
$super.setup.apply(this, arguments);
};
diff --git a/jstests/concurrency/fsm_workloads/indexed_insert_wildcard.js b/jstests/concurrency/fsm_workloads/indexed_insert_wildcard.js
index aaa0a1140f9..c1f08b7a876 100644
--- a/jstests/concurrency/fsm_workloads/indexed_insert_wildcard.js
+++ b/jstests/concurrency/fsm_workloads/indexed_insert_wildcard.js
@@ -8,20 +8,9 @@
*/
load('jstests/concurrency/fsm_libs/extend_workload.js'); // For extendWorkload().
load('jstests/concurrency/fsm_workloads/indexed_insert_base.js'); // For $config().
-load('jstests/libs/discover_topology.js'); // For findDataBearingNodes().
var $config = extendWorkload($config, function($config, $super) {
$config.setup = function init(db, collName) {
- // Enable the test flag required in order to build $** indexes on all data bearing nodes.
- // TODO SERVER-36198: Remove this.
- const hosts = DiscoverTopology.findDataBearingNodes(db.getMongo());
- for (let host of hosts) {
- const conn = new Mongo(host);
- const adminDB = conn.getDB("admin");
- assert.commandWorked(
- adminDB.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- }
-
$super.setup.apply(this, arguments);
};
diff --git a/jstests/concurrency/fsm_workloads/reindex.js b/jstests/concurrency/fsm_workloads/reindex.js
index 32ed49b8e69..ff9d0604ed5 100644
--- a/jstests/concurrency/fsm_workloads/reindex.js
+++ b/jstests/concurrency/fsm_workloads/reindex.js
@@ -96,24 +96,5 @@ var $config = (function() {
query: {reIndex: 0.5, query: 0.5}
};
- function setup(db, collName, cluster) {
- // Enable the test flag required in order to build $** indexes on all data bearing nodes.
- // TODO SERVER-36198: Remove this.
- const hosts = DiscoverTopology.findDataBearingNodes(db.getMongo());
- for (let host of hosts) {
- const conn = new Mongo(host);
- const adminDB = conn.getDB("admin");
- assert.commandWorked(
- adminDB.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- }
- }
-
- return {
- threadCount: 15,
- iterations: 10,
- states: states,
- transitions: transitions,
- data: data,
- setup: setup
- };
+ return {threadCount: 15, iterations: 10, states: states, transitions: transitions, data: data};
})();
diff --git a/jstests/libs/discover_topology.js b/jstests/libs/discover_topology.js
index bd99c240438..7fb1c79c427 100644
--- a/jstests/libs/discover_topology.js
+++ b/jstests/libs/discover_topology.js
@@ -126,36 +126,6 @@ var DiscoverTopology = (function() {
}
return findConnectedNodesViaMongos(conn, options);
- },
-
- /**
- * Return a list of nodes that store data.
- * TODO SERVER-36198: Remove this.
- */
- findDataBearingNodes: function findDataBearingNodes(conn) {
- const topology = DiscoverTopology.findConnectedNodes(conn);
- const hostList = [];
- if (topology.type === Topology.kStandalone) {
- hostList.push(topology.mongod);
- } else if (topology.type === Topology.kReplicaSet) {
- hostList.push(...topology.nodes);
- } else if (topology.type === Topology.kShardedCluster) {
- for (let shardName of Object.keys(topology.shards)) {
- const shard = topology.shards[shardName];
-
- if (shard.type === Topology.kStandalone) {
- hostList.push(shard.mongod);
- } else if (shard.type === Topology.kReplicaSet) {
- hostList.push(...shard.nodes);
- } else {
- throw new Error('Unrecognized topology format: ' + tojson(topology));
- }
- }
- } else {
- throw new Error('Unrecognized topology format: ' + tojson(topology));
- }
-
- return hostList;
}
};
})();
diff --git a/jstests/multiVersion/wildcard_index_feature_compatability_version.js b/jstests/multiVersion/wildcard_index_feature_compatability_version.js
index 315c5452ca8..22af526ac1b 100644
--- a/jstests/multiVersion/wildcard_index_feature_compatability_version.js
+++ b/jstests/multiVersion/wildcard_index_feature_compatability_version.js
@@ -16,11 +16,8 @@
TestData.skipCheckDBHashes = true; // Skip db hashes when restarting the replset.
- const nodeOptions40 = {binVersion: "last-stable", setParameter: {}};
- const nodeOptions42 = {
- binVersion: "latest",
- setParameter: {internalQueryAllowAllPathsIndexes: 1}
- };
+ const nodeOptions40 = {binVersion: "last-stable"};
+ const nodeOptions42 = {binVersion: "latest"};
// Set up a new replSet consisting of 3 nodes, initially running on 4.0 binaries.
const rst = new ReplSetTest({nodes: 3, nodeOptions: nodeOptions40});
diff --git a/jstests/noPassthroughWithMongod/wildcard_and_text_indexes.js b/jstests/noPassthroughWithMongod/wildcard_and_text_indexes.js
index 58677209ddf..945ef3502b7 100644
--- a/jstests/noPassthroughWithMongod/wildcard_and_text_indexes.js
+++ b/jstests/noPassthroughWithMongod/wildcard_and_text_indexes.js
@@ -39,61 +39,51 @@
assert.commandWorked(coll.insert({_id: 2, a: 1, _fts: 2, textToSearch: "bananas"}));
assert.commandWorked(coll.insert({_id: 3, a: 1, _fts: 3}));
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- try {
- // Build a wildcard index, and verify that it can be used to query for the field '_fts'.
- assert.commandWorked(coll.createIndex({"$**": 1}));
- assertWildcardQuery({_fts: {$gt: 0, $lt: 4}}, '_fts');
+ // Build a wildcard index, and verify that it can be used to query for the field '_fts'.
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+ assertWildcardQuery({_fts: {$gt: 0, $lt: 4}}, '_fts');
- // Perform the tests below for simple and compound $text indexes.
- for (let textIndex of[{'$**': 'text'}, {a: 1, '$**': 'text'}]) {
- // Build the appropriate text index.
- assert.commandWorked(coll.createIndex(textIndex, {name: "textIndex"}));
+ // Perform the tests below for simple and compound $text indexes.
+ for (let textIndex of[{'$**': 'text'}, {a: 1, '$**': 'text'}]) {
+ // Build the appropriate text index.
+ assert.commandWorked(coll.createIndex(textIndex, {name: "textIndex"}));
- // Confirm that the $** index can still be used to query for the '_fts' field outside of
- // a $text query.
- assertWildcardQuery({_fts: {$gt: 0, $lt: 4}}, '_fts');
+ // Confirm that the $** index can still be used to query for the '_fts' field outside of
+ // $text queries.
+ assertWildcardQuery({_fts: {$gt: 0, $lt: 4}}, '_fts');
- // Confirm that $** does not generate a candidate plan for $text search, including cases
- // when the query filter contains a compound field in the $text index.
- const textQuery =
- Object.assign(textIndex.a ? {a: 1} : {}, {$text: {$search: 'banana'}});
- let explainOut = assert.commandWorked(coll.find(textQuery).explain("executionStats"));
- assert(planHasStage(coll.getDB(), explainOut.queryPlanner.winningPlan, "TEXT"));
- assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
- assert.eq(explainOut.executionStats.nReturned, 2);
+ // Confirm that $** does not generate a candidate plan for $text search, including cases
+ // when the query filter contains a compound field in the $text index.
+ const textQuery = Object.assign(textIndex.a ? {a: 1} : {}, {$text: {$search: 'banana'}});
+ let explainOut = assert.commandWorked(coll.find(textQuery).explain("executionStats"));
+ assert(planHasStage(coll.getDB(), explainOut.queryPlanner.winningPlan, "TEXT"));
+ assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
+ assert.eq(explainOut.executionStats.nReturned, 2);
- // Confirm that $** does not generate a candidate plan for $text search, including cases
- // where the query filter contains a field which is not present in the text index.
- explainOut =
- assert.commandWorked(coll.find(Object.assign({_fts: {$gt: 0, $lt: 4}}, textQuery))
- .explain("executionStats"));
- assert(planHasStage(coll.getDB(), explainOut.queryPlanner.winningPlan, "TEXT"));
- assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
- assert.eq(explainOut.executionStats.nReturned, 2);
+ // Confirm that $** does not generate a candidate plan for $text search, including cases
+ // where the query filter contains a field which is not present in the text index.
+ explainOut =
+ assert.commandWorked(coll.find(Object.assign({_fts: {$gt: 0, $lt: 4}}, textQuery))
+ .explain("executionStats"));
+ assert(planHasStage(coll.getDB(), explainOut.queryPlanner.winningPlan, "TEXT"));
+ assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
+ assert.eq(explainOut.executionStats.nReturned, 2);
- // Confirm that the $** index can be used alongside a $text predicate in an $or.
- explainOut = assert.commandWorked(
- coll.find({$or: [{_fts: 3}, textQuery]}).explain("executionStats"));
- assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
- assert.eq(explainOut.executionStats.nReturned, 3);
+ // Confirm that the $** index can be used alongside a $text predicate in an $or.
+ explainOut = assert.commandWorked(
+ coll.find({$or: [{_fts: 3}, textQuery]}).explain("executionStats"));
+ assert.eq(explainOut.queryPlanner.rejectedPlans.length, 0);
+ assert.eq(explainOut.executionStats.nReturned, 3);
- const textOrWildcard = getPlanStages(explainOut.queryPlanner.winningPlan, "OR").shift();
- assert.eq(textOrWildcard.inputStages.length, 2);
- const textBranch = (textOrWildcard.inputStages[0].stage === "TEXT" ? 0 : 1);
- const wildcardBranch = (textBranch + 1) % 2;
- assert.eq(textOrWildcard.inputStages[textBranch].stage, "TEXT");
- assert.eq(textOrWildcard.inputStages[wildcardBranch].stage, "IXSCAN");
- assert.eq(textOrWildcard.inputStages[wildcardBranch].keyPattern, {$_path: 1, _fts: 1});
+ const textOrWildcard = getPlanStages(explainOut.queryPlanner.winningPlan, "OR").shift();
+ assert.eq(textOrWildcard.inputStages.length, 2);
+ const textBranch = (textOrWildcard.inputStages[0].stage === "TEXT" ? 0 : 1);
+ const wildcardBranch = (textBranch + 1) % 2;
+ assert.eq(textOrWildcard.inputStages[textBranch].stage, "TEXT");
+ assert.eq(textOrWildcard.inputStages[wildcardBranch].stage, "IXSCAN");
+ assert.eq(textOrWildcard.inputStages[wildcardBranch].keyPattern, {$_path: 1, _fts: 1});
- // Drop the index so that a different text index can be created.
- assert.commandWorked(coll.dropIndex("textIndex"));
- }
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false}));
+ // Drop the index so that a different text index can be created.
+ assert.commandWorked(coll.dropIndex("textIndex"));
}
})();
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_basic_index_bounds.js b/jstests/noPassthroughWithMongod/wildcard_index_basic_index_bounds.js
index 54fdcdfba58..776c9d9fc50 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_basic_index_bounds.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_basic_index_bounds.js
@@ -196,33 +196,23 @@
}
}
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- try {
- // Test a $** index that indexes the entire document.
- runWildcardIndexTest({'$**': 1}, null, ['a', 'b.c', 'b.d.e', 'b.f']);
-
- // Test a $** index on a single subtree.
- runWildcardIndexTest({'a.$**': 1}, null, ['a']);
- runWildcardIndexTest({'b.$**': 1}, null, ['b.c', 'b.d.e', 'b.f']);
- runWildcardIndexTest({'b.d.$**': 1}, null, ['b.d.e']);
-
- // Test a $** index which includes a subset of paths.
- runWildcardIndexTest({'$**': 1}, {a: 1}, ['a']);
- runWildcardIndexTest({'$**': 1}, {b: 1}, ['b.c', 'b.d.e', 'b.f']);
- runWildcardIndexTest({'$**': 1}, {'b.d': 1}, ['b.d.e']);
- runWildcardIndexTest({'$**': 1}, {a: 1, 'b.d': 1}, ['a', 'b.d.e']);
-
- // Test a $** index which excludes a subset of paths.
- runWildcardIndexTest({'$**': 1}, {a: 0}, ['b.c', 'b.d.e', 'b.f']);
- runWildcardIndexTest({'$**': 1}, {b: 0}, ['a']);
- runWildcardIndexTest({'$**': 1}, {'b.d': 0}, ['a', 'b.c', 'b.f']);
- runWildcardIndexTest({'$**': 1}, {a: 0, 'b.d': 0}, ['b.c', 'b.f']);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false}));
- }
+ // Test a $** index that indexes the entire document.
+ runWildcardIndexTest({'$**': 1}, null, ['a', 'b.c', 'b.d.e', 'b.f']);
+
+ // Test a $** index on a single subtree.
+ runWildcardIndexTest({'a.$**': 1}, null, ['a']);
+ runWildcardIndexTest({'b.$**': 1}, null, ['b.c', 'b.d.e', 'b.f']);
+ runWildcardIndexTest({'b.d.$**': 1}, null, ['b.d.e']);
+
+ // Test a $** index which includes a subset of paths.
+ runWildcardIndexTest({'$**': 1}, {a: 1}, ['a']);
+ runWildcardIndexTest({'$**': 1}, {b: 1}, ['b.c', 'b.d.e', 'b.f']);
+ runWildcardIndexTest({'$**': 1}, {'b.d': 1}, ['b.d.e']);
+ runWildcardIndexTest({'$**': 1}, {a: 1, 'b.d': 1}, ['a', 'b.d.e']);
+
+ // Test a $** index which excludes a subset of paths.
+ runWildcardIndexTest({'$**': 1}, {a: 0}, ['b.c', 'b.d.e', 'b.f']);
+ runWildcardIndexTest({'$**': 1}, {b: 0}, ['a']);
+ runWildcardIndexTest({'$**': 1}, {'b.d': 0}, ['a', 'b.c', 'b.f']);
+ runWildcardIndexTest({'$**': 1}, {a: 0, 'b.d': 0}, ['b.c', 'b.f']);
})();
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_cached_plans.js b/jstests/noPassthroughWithMongod/wildcard_index_cached_plans.js
index dea4b0733d1..704ce77cd7e 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_cached_plans.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_cached_plans.js
@@ -7,9 +7,6 @@
load('jstests/libs/analyze_plan.js'); // For getPlanStage().
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
const coll = db.wildcard_cached_plans;
coll.drop();
assert.commandWorked(coll.createIndex({"b.$**": 1}));
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_collation.js b/jstests/noPassthroughWithMongod/wildcard_index_collation.js
index 92addd75de6..6f31c12bafb 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_collation.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_collation.js
@@ -49,80 +49,71 @@
tojson(collation) + " not found: " + tojson(indexSpecs));
}
- try {
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- // Recreate the collection with a default case-insensitive collation.
- assert.commandWorked(
- db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 1}}));
-
- // Confirm that the $** index inherits the collection's default collation.
- assert.commandWorked(coll.createIndex({"$**": 1}));
- assertIndexHasCollation({"$**": 1}, {
- locale: "en_US",
- caseLevel: false,
- caseFirst: "off",
- strength: 1,
- numericOrdering: false,
- alternate: "non-ignorable",
- maxVariable: "punct",
- normalization: false,
- backwards: false,
- version: "57.1",
- });
-
- // Insert a series of documents whose fieldnames and values differ only by case.
- assert.commandWorked(coll.insert({a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5}));
- assert.commandWorked(coll.insert({a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}));
- assert.commandWorked(coll.insert({A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5}));
- assert.commandWorked(coll.insert({A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}));
-
- // Confirm that only the document's values adhere to the case-insensitive collation. The
- // field paths, which are also present in the $** index keys, are evaluated using simple
- // binary comparison; so for instance, path "a.b" does *not* match path "A.B".
- assertWildcardIndexAnswersQuery({"a.b": "string"}, [
- {a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5},
- {a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}
- ]);
- assertWildcardIndexAnswersQuery({"A.B": "string"}, [
- {A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5},
- {A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}
- ]);
-
- // All documents in the collection are returned if we query over both upper- and lower-case
- // fieldnames, or when the fieldname has a consistent case across all documents.
- const allDocs = coll.find({}, {_id: 0}).toArray();
- assertWildcardIndexAnswersQuery({$or: [{"a.c": "string"}, {"A.C": "string"}]}, allDocs);
- assertWildcardIndexAnswersQuery({d: "string"}, allDocs);
-
- // Confirm that the $** index also differentiates between upper and lower fieldname case
- // when querying fields which do not contain string values.
- assertWildcardIndexAnswersQuery({e: 5}, [
- {a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5},
- {a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}
- ]);
- assertWildcardIndexAnswersQuery({E: 5}, [
- {A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5},
- {A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}
- ]);
-
- // Confirm that the $** index produces a covered plan for a query on non-string, non-object,
- // non-array values.
- assert(isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, e: 1})));
- assert(isIndexOnly(coll.getDB(), winningPlan({E: 5}, {_id: 0, E: 1})));
-
- // Confirm that the $** index differentiates fieldname case when attempting to cover.
- assert(!isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, E: 1})));
- assert(!isIndexOnly(coll.getDB(), winningPlan({E: 5}, {_id: 0, e: 1})));
-
- // Confirm that attempting to project the virtual $_path field which is present in $** index
- // keys produces a non-covered solution, which nonetheless returns the correct results.
- assert(!isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, e: 1, $_path: 1})));
- assertWildcardIndexAnswersQuery({e: 5}, [{e: 5}, {e: 5}], {_id: 0, e: 1, $_path: 1});
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ // Recreate the collection with a default case-insensitive collation.
+ assert.commandWorked(
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 1}}));
+
+ // Confirm that the $** index inherits the collection's default collation.
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+ assertIndexHasCollation({"$**": 1}, {
+ locale: "en_US",
+ caseLevel: false,
+ caseFirst: "off",
+ strength: 1,
+ numericOrdering: false,
+ alternate: "non-ignorable",
+ maxVariable: "punct",
+ normalization: false,
+ backwards: false,
+ version: "57.1",
+ });
+
+ // Insert a series of documents whose fieldnames and values differ only by case.
+ assert.commandWorked(coll.insert({a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5}));
+ assert.commandWorked(coll.insert({a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}));
+ assert.commandWorked(coll.insert({A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5}));
+ assert.commandWorked(coll.insert({A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}));
+
+ // Confirm that only the document's values adhere to the case-insensitive collation. The field
+ // paths, which are also present in the $** index keys, are evaluated using simple binary
+ // comparison; so for instance, path "a.b" does *not* match path "A.B".
+ assertWildcardIndexAnswersQuery({"a.b": "string"}, [
+ {a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5},
+ {a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}
+ ]);
+ assertWildcardIndexAnswersQuery({"A.B": "string"}, [
+ {A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5},
+ {A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}
+ ]);
+
+ // All documents in the collection are returned if we query over both upper- and lower-case
+ // fieldnames, or when the fieldname has a consistent case across all documents.
+ const allDocs = coll.find({}, {_id: 0}).toArray();
+ assertWildcardIndexAnswersQuery({$or: [{"a.c": "string"}, {"A.C": "string"}]}, allDocs);
+ assertWildcardIndexAnswersQuery({d: "string"}, allDocs);
+
+ // Confirm that the $** index also differentiates between upper and lower fieldname case when
+ // querying fields which do not contain string values.
+ assertWildcardIndexAnswersQuery({e: 5}, [
+ {a: {b: "string", c: "STRING"}, d: "sTrInG", e: 5},
+ {a: {b: "STRING", c: "string"}, d: "StRiNg", e: 5}
+ ]);
+ assertWildcardIndexAnswersQuery({E: 5}, [
+ {A: {B: "string", C: "STRING"}, d: "sTrInG", E: 5},
+ {A: {B: "STRING", C: "string"}, d: "StRiNg", E: 5}
+ ]);
+
+ // Confirm that the $** index produces a covered plan for a query on non-string, non-object,
+ // non-array values.
+ assert(isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, e: 1})));
+ assert(isIndexOnly(coll.getDB(), winningPlan({E: 5}, {_id: 0, E: 1})));
+
+ // Confirm that the $** index differentiates fieldname case when attempting to cover.
+ assert(!isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, E: 1})));
+ assert(!isIndexOnly(coll.getDB(), winningPlan({E: 5}, {_id: 0, e: 1})));
+
+ // Confirm that attempting to project the virtual $_path field which is present in $** index
+ // keys produces a non-covered solution, which nonetheless returns the correct results.
+ assert(!isIndexOnly(coll.getDB(), winningPlan({e: 5}, {_id: 0, e: 1, $_path: 1})));
+ assertWildcardIndexAnswersQuery({e: 5}, [{e: 5}, {e: 5}], {_id: 0, e: 1, $_path: 1});
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_covered_queries.js b/jstests/noPassthroughWithMongod/wildcard_index_covered_queries.js
index ecb182d45af..b70a0d1e5a3 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_covered_queries.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_covered_queries.js
@@ -44,51 +44,41 @@
coll.find(query, proj).hint({$natural: 1}).toArray());
}
- try {
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- // Create a new collection and build a $** index on it.
- const bulk = coll.initializeUnorderedBulkOp();
- for (let i = 0; i < 200; i++) {
- bulk.insert({a: {b: i, c: `${(i+1)}`}, d: (i + 2)});
- }
- assert.commandWorked(bulk.execute());
- assert.commandWorked(coll.createIndex({"$**": 1}));
-
- // Verify that the $** index can cover an exact match on an integer value.
- assertWildcardProvidesCoveredSolution({"a.b": 10}, {_id: 0, "a.b": 1});
-
- // Verify that the $** index can cover an exact match on a string value.
- assertWildcardProvidesCoveredSolution({"a.c": "10"}, {_id: 0, "a.c": 1});
-
- // Verify that the $** index can cover a range query for integer values.
- assertWildcardProvidesCoveredSolution({"a.b": {$gt: 10, $lt: 99}}, {_id: 0, "a.b": 1});
-
- // Verify that the $** index can cover a range query for string values.
- assertWildcardProvidesCoveredSolution({"a.c": {$gt: "10", $lt: "99"}}, {_id: 0, "a.c": 1});
-
- // Verify that the $** index can cover an $in query for integer values.
- assertWildcardProvidesCoveredSolution({"a.b": {$in: [0, 50, 100, 150]}},
- {_id: 0, "a.b": 1});
-
- // Verify that the $** index can cover an $in query for string values.
- assertWildcardProvidesCoveredSolution({"a.c": {$in: ["0", "50", "100", "150"]}},
- {_id: 0, "a.c": 1});
-
- // Verify that attempting to project the virtual $_path field from the $** keyPattern will
- // fail to do so and will instead produce a non-covered query. However, this query will
- // nonetheless output the correct results.
- const shouldFailToCover = true;
- assertWildcardProvidesCoveredSolution(
- {d: {$in: [0, 25, 50, 75, 100]}}, {_id: 0, d: 1, $_path: 1}, shouldFailToCover);
-
- // Verify that predicates which produce inexact-fetch bounds are not covered by a $** index.
- assertWildcardProvidesCoveredSolution(
- {d: {$elemMatch: {$eq: 50}}}, {_id: 0, d: 1}, shouldFailToCover);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
+ // Create a new collection and build a $** index on it.
+ const bulk = coll.initializeUnorderedBulkOp();
+ for (let i = 0; i < 200; i++) {
+ bulk.insert({a: {b: i, c: `${(i+1)}`}, d: (i + 2)});
}
+ assert.commandWorked(bulk.execute());
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+
+ // Verify that the $** index can cover an exact match on an integer value.
+ assertWildcardProvidesCoveredSolution({"a.b": 10}, {_id: 0, "a.b": 1});
+
+ // Verify that the $** index can cover an exact match on a string value.
+ assertWildcardProvidesCoveredSolution({"a.c": "10"}, {_id: 0, "a.c": 1});
+
+ // Verify that the $** index can cover a range query for integer values.
+ assertWildcardProvidesCoveredSolution({"a.b": {$gt: 10, $lt: 99}}, {_id: 0, "a.b": 1});
+
+ // Verify that the $** index can cover a range query for string values.
+ assertWildcardProvidesCoveredSolution({"a.c": {$gt: "10", $lt: "99"}}, {_id: 0, "a.c": 1});
+
+ // Verify that the $** index can cover an $in query for integer values.
+ assertWildcardProvidesCoveredSolution({"a.b": {$in: [0, 50, 100, 150]}}, {_id: 0, "a.b": 1});
+
+ // Verify that the $** index can cover an $in query for string values.
+ assertWildcardProvidesCoveredSolution({"a.c": {$in: ["0", "50", "100", "150"]}},
+ {_id: 0, "a.c": 1});
+
+ // Verify that attempting to project the virtual $_path field from the $** keyPattern will fail
+ // to do so and will instead produce a non-covered query. However, this query will nonetheless
+ // output the correct results.
+ const shouldFailToCover = true;
+ assertWildcardProvidesCoveredSolution(
+ {d: {$in: [0, 25, 50, 75, 100]}}, {_id: 0, d: 1, $_path: 1}, shouldFailToCover);
+
+ // Verify that predicates which produce inexact-fetch bounds are not covered by a $** index.
+ assertWildcardProvidesCoveredSolution(
+ {d: {$elemMatch: {$eq: 50}}}, {_id: 0, d: 1}, shouldFailToCover);
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_empty_arrays.js b/jstests/noPassthroughWithMongod/wildcard_index_empty_arrays.js
index 77b20b5ba8e..7b5e763bbad 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_empty_arrays.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_empty_arrays.js
@@ -11,40 +11,31 @@
const assertArrayEq = (l, r) => assert(arrayEq(l, r), tojson(l) + " != " + tojson(r));
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- try {
- const indexWildcard = {"$**": 1};
- assert.commandWorked(coll.createIndex(indexWildcard));
-
- assert.commandWorked(coll.insert({a: 1, b: 1, c: [], d: {e: [5, 6]}}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: [1, 2], d: {e: []}}));
- assert.commandWorked(coll.insert({a: 1, b: 2, c: [3, 4], d: {e: [7, 8]}, f: [{g: []}]}));
- assert.commandWorked(coll.insert({a: 2, b: [[]], c: 1, d: 4}));
-
- // $** index matches empty array.
- assertArrayEq(coll.find({c: []}, {_id: 0}).hint(indexWildcard).toArray(),
- [{a: 1, b: 1, c: [], d: {e: [5, 6]}}]);
-
- // $** index supports equality to array offset.
- assertArrayEq(coll.find({"c.0": 1}, {_id: 0}).hint(indexWildcard).toArray(),
- [{a: 2, b: 2, c: [1, 2], d: {e: []}}]);
-
- // $** index matches empty array nested in object.
- assertArrayEq(coll.find({"d.e": []}, {_id: 0}).hint(indexWildcard).toArray(),
- [{a: 2, b: 2, c: [1, 2], d: {e: []}}]);
-
- // $** index matches empty array nested within an array of objects.
- assertArrayEq(coll.find({"f.0.g": []}, {_id: 0}).hint(indexWildcard).toArray(),
- [{a: 1, b: 2, c: [3, 4], d: {e: [7, 8]}, f: [{g: []}]}]);
-
- // $** index matches empty array nested within an array.
- assertArrayEq(coll.find({"b": []}, {_id: 0}).hint(indexWildcard).toArray(),
- [{a: 2, b: [[]], c: 1, d: 4}]);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ const indexWildcard = {"$**": 1};
+ assert.commandWorked(coll.createIndex(indexWildcard));
+
+ assert.commandWorked(coll.insert({a: 1, b: 1, c: [], d: {e: [5, 6]}}));
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: [1, 2], d: {e: []}}));
+ assert.commandWorked(coll.insert({a: 1, b: 2, c: [3, 4], d: {e: [7, 8]}, f: [{g: []}]}));
+ assert.commandWorked(coll.insert({a: 2, b: [[]], c: 1, d: 4}));
+
+ // $** index matches empty array.
+ assertArrayEq(coll.find({c: []}, {_id: 0}).hint(indexWildcard).toArray(),
+ [{a: 1, b: 1, c: [], d: {e: [5, 6]}}]);
+
+ // $** index supports equality to array offset.
+ assertArrayEq(coll.find({"c.0": 1}, {_id: 0}).hint(indexWildcard).toArray(),
+ [{a: 2, b: 2, c: [1, 2], d: {e: []}}]);
+
+ // $** index matches empty array nested in object.
+ assertArrayEq(coll.find({"d.e": []}, {_id: 0}).hint(indexWildcard).toArray(),
+ [{a: 2, b: 2, c: [1, 2], d: {e: []}}]);
+
+ // $** index matches empty array nested within an array of objects.
+ assertArrayEq(coll.find({"f.0.g": []}, {_id: 0}).hint(indexWildcard).toArray(),
+ [{a: 1, b: 2, c: [3, 4], d: {e: [7, 8]}, f: [{g: []}]}]);
+
+ // $** index matches empty array nested within an array.
+ assertArrayEq(coll.find({"b": []}, {_id: 0}).hint(indexWildcard).toArray(),
+ [{a: 2, b: [[]], c: 1, d: 4}]);
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_equality_to_empty_obj.js b/jstests/noPassthroughWithMongod/wildcard_index_equality_to_empty_obj.js
index cdc0d34a28f..10e1b1186ce 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_equality_to_empty_obj.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_equality_to_empty_obj.js
@@ -23,69 +23,56 @@
{_id: 10, a: [0, {b: {}}]},
]));
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- try {
- assert.commandWorked(coll.createIndex({"$**": 1}));
+ assert.commandWorked(coll.createIndex({"$**": 1}));
- // Test that a comparison to empty object query returns the expected results when the $**
- // index is hinted.
- let results = coll.find({a: {}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
- assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}]);
+ // Test that a comparison to empty object query returns the expected results when the $** index
+ // is hinted.
+ let results = coll.find({a: {}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
+ assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}]);
- // Result set should be the same as when hinting a COLLSCAN and with no hint.
- assert.eq(results,
- coll.find({a: {}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
- assert.eq(results, coll.find({a: {}}, {_id: 1}).sort({_id: 1}).toArray());
+ // Result set should be the same as when hinting a COLLSCAN and with no hint.
+ assert.eq(results, coll.find({a: {}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
+ assert.eq(results, coll.find({a: {}}, {_id: 1}).sort({_id: 1}).toArray());
- // Repeat the above query, but express it using $lte:{}, which is a synonym for $eq:{}.
- results = coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
- assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}]);
- assert.eq(
- results,
- coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
- assert.eq(results, coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).toArray());
+ // Repeat the above query, but express it using $lte:{}, which is a synonym for $eq:{}.
+ results = coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
+ assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}]);
+ assert.eq(results,
+ coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
+ assert.eq(results, coll.find({a: {$lte: {}}}, {_id: 1}).sort({_id: 1}).toArray());
- // Test that an inequality to empty object query results in an error when the $** index is
- // hinted.
- assert.throws(
- () => coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray());
+ // Test that an inequality to empty object query results in an error when the $** index is
+ // hinted.
+ assert.throws(
+ () => coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray());
- // Test that an inequality to empty object query returns the expected results in the
- // presence of the $** index.
- results = coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).toArray();
- assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}, {_id: 7}, {_id: 9}, {_id: 10}]);
+ // Test that an inequality to empty object query returns the expected results in the presence of
+ // the $** index.
+ results = coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).toArray();
+ assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}, {_id: 7}, {_id: 9}, {_id: 10}]);
- // Result set should be the same as when hinting a COLLSCAN and with no hint.
- assert.eq(
- results,
- coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
- assert.eq(results, coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).toArray());
+ // Result set should be the same as when hinting a COLLSCAN and with no hint.
+ assert.eq(results,
+ coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
+ assert.eq(results, coll.find({a: {$gte: {}}}, {_id: 1}).sort({_id: 1}).toArray());
- // Test that an $in with an empty object returns the expected results when the $** index is
- // hinted.
- results =
- coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
- assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}, {_id: 8}]);
+ // Test that an $in with an empty object returns the expected results when the $** index is
+ // hinted.
+ results = coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
+ assert.eq(results, [{_id: 3}, {_id: 4}, {_id: 6}, {_id: 8}]);
- // Result set should be the same as when hinting a COLLSCAN and with no hint.
- assert.eq(
- results,
- coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
- assert.eq(results, coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).toArray());
+ // Result set should be the same as when hinting a COLLSCAN and with no hint.
+ assert.eq(
+ results,
+ coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
+ assert.eq(results, coll.find({a: {$in: [3, {}]}}, {_id: 1}).sort({_id: 1}).toArray());
- // Test that a wildcard index can support equality to an empty object on a dotted field.
- results = coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
- assert.eq(results, [{_id: 9}, {_id: 10}]);
+ // Test that a wildcard index can support equality to an empty object on a dotted field.
+ results = coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).hint({"$**": 1}).toArray();
+ assert.eq(results, [{_id: 9}, {_id: 10}]);
- // Result set should be the same as when hinting a COLLSCAN and with no hint.
- assert.eq(
- results,
- coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
- assert.eq(results, coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).toArray());
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ // Result set should be the same as when hinting a COLLSCAN and with no hint.
+ assert.eq(results,
+ coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).hint({$natural: 1}).toArray());
+ assert.eq(results, coll.find({"a.b": {$eq: {}}}, {_id: 1}).sort({_id: 1}).toArray());
}());
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_filter.js b/jstests/noPassthroughWithMongod/wildcard_index_filter.js
index 3cd0d535e91..f8dd7182267 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_filter.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_filter.js
@@ -44,58 +44,45 @@
assert.eq(planStage.indexName, expectedIndexName, tojson(planStage));
}
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
+ const indexWildcard = {"$**": 1};
+ const indexA = {"a": 1};
+ assert.commandWorked(coll.createIndex(indexWildcard));
+ assert.commandWorked(coll.createIndex(indexA));
- try {
- const indexWildcard = {"$**": 1};
- const indexA = {"a": 1};
- assert.commandWorked(coll.createIndex(indexWildcard));
- assert.commandWorked(coll.createIndex(indexA));
+ assert.commandWorked(coll.insert({a: "a"}));
- assert.commandWorked(coll.insert({a: "a"}));
+ // Filtering on $** index. $** index is used over another index.
+ assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexWildcard], {a: "a"}, "$**_1");
- // Filtering on $** index. $** index is used over another index.
- assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexWildcard], {a: "a"}, "$**_1");
+ // Filtering on regular index. $** index is not used over another index.
+ assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexA], {a: "a"}, "a_1");
- // Filtering on regular index. $** index is not used over another index.
- assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexA], {a: "a"}, "a_1");
+ assert.commandWorked(coll.insert({a: "a", b: "b"}));
- assert.commandWorked(coll.insert({a: "a", b: "b"}));
+ const indexAB = {"a": 1, "b": 1};
+ assert.commandWorked(coll.createIndex(indexAB));
- const indexAB = {"a": 1, "b": 1};
- assert.commandWorked(coll.createIndex(indexAB));
+ // Filtering on $** index. $** index is used over another index for compound query.
+ assertExpectedIndexAnswersQueryWithFilter(
+ {a: "a", b: "b"}, [indexWildcard], {a: "a", b: "b"}, "$**_1");
- // Filtering on $** index. $** index is used over another index for compound query.
- assertExpectedIndexAnswersQueryWithFilter(
- {a: "a", b: "b"}, [indexWildcard], {a: "a", b: "b"}, "$**_1");
+ // Filtering on regular compound index. Check that $** index is not used over another index
+ // for compound query.
+ assertExpectedIndexAnswersQueryWithFilter(
+ {a: "a", b: "b"}, [indexAB], {a: "a", b: "b"}, "a_1_b_1");
- // Filtering on regular compound index. Check that $** index is not used over another index
- // for compound query.
- assertExpectedIndexAnswersQueryWithFilter(
- {a: "a", b: "b"}, [indexAB], {a: "a", b: "b"}, "a_1_b_1");
+ // Filtering on $** index while hinting on another index. Index filter is prioritized.
+ assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexWildcard], {a: "a"}, "$**_1", indexA);
- // Filtering on $** index while hinting on another index. Index filter is prioritized.
- assertExpectedIndexAnswersQueryWithFilter(
- {a: "a"}, [indexWildcard], {a: "a"}, "$**_1", indexA);
+ // Filtering on regular index while hinting on $** index. Index filter is prioritized.
+ assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexA], {a: "a"}, "a_1", indexWildcard);
- // Filtering on regular index while hinting on $** index. Index filter is prioritized.
- assertExpectedIndexAnswersQueryWithFilter(
- {a: "a"}, [indexA], {a: "a"}, "a_1", indexWildcard);
+ // Index filter for $** index does not apply when query does not match filter query shape.
+ assertExpectedIndexAnswersQueryWithFilter({b: "b"}, [indexWildcard], {a: "a"}, "a_1", indexA);
- // Index filter for $** index does not apply when query does not match filter query shape.
- assertExpectedIndexAnswersQueryWithFilter(
- {b: "b"}, [indexWildcard], {a: "a"}, "a_1", indexA);
+ const indexAWildcard = {"a.$**": 1};
+ assert.commandWorked(coll.createIndex(indexAWildcard));
- const indexAWildcard = {"a.$**": 1};
- assert.commandWorked(coll.createIndex(indexAWildcard));
-
- // Filtering on a path specified $** index. Check that the $** is used over other indices.
- assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexAWildcard], {a: "a"}, "a.$**_1");
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false}));
- }
+ // Filtering on a path specified $** index. Check that the $** is used over other indices.
+ assertExpectedIndexAnswersQueryWithFilter({a: "a"}, [indexAWildcard], {a: "a"}, "a.$**_1");
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_hint.js b/jstests/noPassthroughWithMongod/wildcard_index_hint.js
index f4a8d8fb878..9f88e248c3d 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_hint.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_hint.js
@@ -30,92 +30,77 @@
assertArrayEq(wildcardResults, expectedResults);
}
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- try {
- assert.commandWorked(db.createCollection(coll.getName()));
-
- // Check that error is thrown if the hinted index doesn't exist.
- assert.commandFailedWithCode(
- db.runCommand({find: coll.getName(), filter: {"a": 1}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- assert.commandWorked(coll.createIndex({"$**": 1}));
-
- assert.commandWorked(coll.insert({_id: 10, a: 1, b: 1, c: {d: 1, e: 1}}));
- assert.commandWorked(coll.insert({a: 1, b: 2, c: {d: 2, e: 2}}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: {d: 1, e: 2}}));
- assert.commandWorked(coll.insert({a: 2, b: 1, c: {d: 2, e: 2}}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}}));
-
- // Hint a $** index without a competing index.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1},
- {"$**": 1},
- "$**_1",
- [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
-
- assert.commandWorked(coll.createIndex({"a": 1}));
-
- // Hint a $** index with a competing index.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1},
- {"$**": 1},
- "$**_1",
- [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
-
- // Hint a $** index with a competing _id index.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1, "_id": 10}, {"$**": 1}, "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}]);
-
- // Hint a regular index with a competing $** index.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1},
- {"a": 1},
- "a_1",
- [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
-
- // Query on fields that not all documents in the collection have with $** index hint.
- assertExpectedIndexAnswersQueryWithHint(
- {"c.d": 1},
- {"$**": 1},
- "$**_1",
- [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 2, b: 2, c: {d: 1, e: 2}}]);
-
- // Adding another wildcard index with a path specified.
- assert.commandWorked(coll.createIndex({"c.$**": 1}));
-
- // Hint on path that is not in query argument.
- assert.commandFailedWithCode(
- db.runCommand({find: coll.getName(), filter: {"a": 1}, hint: {"c.$**": 1}}),
- ErrorCodes.BadValue);
-
- // Hint on a path specified $** index.
- assertExpectedIndexAnswersQueryWithHint(
- {"c.d": 1},
- {"c.$**": 1},
- "c.$**_1",
- [{a: 2, b: 2, c: {d: 1, e: 2}}, {a: 1, b: 1, c: {d: 1, e: 1}}]);
-
- // Min/max with $** index hint.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), filter: {"b": 1}, min: {"a": 1}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Hint a $** index on a query with compound fields.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1, "c.e": 1}, {"$**": 1}, "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}]);
-
- // Hint a $** index by name.
- assertExpectedIndexAnswersQueryWithHint(
- {"a": 1},
- "$**_1",
- "$**_1",
- [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ assert.commandWorked(db.createCollection(coll.getName()));
+
+ // Check that error is thrown if the hinted index doesn't exist.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 1}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+
+ assert.commandWorked(coll.insert({_id: 10, a: 1, b: 1, c: {d: 1, e: 1}}));
+ assert.commandWorked(coll.insert({a: 1, b: 2, c: {d: 2, e: 2}}));
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: {d: 1, e: 2}}));
+ assert.commandWorked(coll.insert({a: 2, b: 1, c: {d: 2, e: 2}}));
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}}));
+
+ // Hint a $** index without a competing index.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1},
+ {"$**": 1},
+ "$**_1",
+ [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
+
+ assert.commandWorked(coll.createIndex({"a": 1}));
+
+ // Hint a $** index with a competing index.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1},
+ {"$**": 1},
+ "$**_1",
+ [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
+
+ // Hint a $** index with a competing _id index.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1, "_id": 10}, {"$**": 1}, "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}]);
+
+ // Hint a regular index with a competing $** index.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1}, {"a": 1}, "a_1", [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
+
+ // Query on fields that not all documents in the collection have with $** index hint.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"c.d": 1},
+ {"$**": 1},
+ "$**_1",
+ [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 2, b: 2, c: {d: 1, e: 2}}]);
+
+ // Adding another wildcard index with a path specified.
+ assert.commandWorked(coll.createIndex({"c.$**": 1}));
+
+ // Hint on path that is not in query argument.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 1}, hint: {"c.$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Hint on a path specified $** index.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"c.d": 1},
+ {"c.$**": 1},
+ "c.$**_1",
+ [{a: 2, b: 2, c: {d: 1, e: 2}}, {a: 1, b: 1, c: {d: 1, e: 1}}]);
+
+ // Min/max with $** index hint.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"b": 1}, min: {"a": 1}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Hint a $** index on a query with compound fields.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1, "c.e": 1}, {"$**": 1}, "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}]);
+
+ // Hint a $** index by name.
+ assertExpectedIndexAnswersQueryWithHint(
+ {"a": 1}, "$**_1", "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]);
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_minmax.js b/jstests/noPassthroughWithMongod/wildcard_index_minmax.js
index 006e92069c1..85b4eca86d0 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_minmax.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_minmax.js
@@ -11,85 +11,71 @@
const assertArrayEq = (l, r) => assert(arrayEq(l, r), tojson(l) + " != " + tojson(r));
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- try {
- assert.commandWorked(coll.createIndex({"$**": 1}));
-
- assert.commandWorked(coll.insert({a: 1, b: 1}));
- assert.commandWorked(coll.insert({a: 1, b: 2}));
- assert.commandWorked(coll.insert({a: 2, b: 1}));
- assert.commandWorked(coll.insert({a: 2, b: 2}));
-
- // Throws error for $** index min.
- assert.commandFailedWithCode(
- db.runCommand({find: coll.getName(), min: {"a": 0.5}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index max.
- assert.commandFailedWithCode(
- db.runCommand({find: coll.getName(), max: {"a": 1.5}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index min/max.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), min: {"a": 0.5}, max: {"a": 1.5}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index min with filter of a different value.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), filter: {"a": 2}, min: {"a": 1}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index max with filter of a different value.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), filter: {"a": 1}, max: {"a": 1.5}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index min and max with filter of a different value.
- assert.commandFailedWithCode(db.runCommand({
- find: coll.getName(),
- filter: {"a": 1},
- min: {"a": 0.5},
- max: {"a": 1.5},
- hint: {"$**": 1}
- }),
- ErrorCodes.BadValue);
-
- // Throws error for $** index min with filter of the same value.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), filter: {"a": 1}, min: {"a": 1}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index max with filter of the same value.
- assert.commandFailedWithCode(
- db.runCommand(
- {find: coll.getName(), filter: {"a": 1}, max: {"a": 1}, hint: {"$**": 1}}),
- ErrorCodes.BadValue);
-
- // Throws error for $** index min and max with filter of the same value.
- assert.commandFailedWithCode(db.runCommand({
- find: coll.getName(),
- filter: {"a": 1},
- min: {"a": 1},
- max: {"a": 1},
- hint: {"$**": 1}
- }),
- ErrorCodes.BadValue);
-
- assert.commandWorked(coll.createIndex({"a": 1}));
-
- // $** index does not interfere with valid min/max.
- assertArrayEq(coll.find({}, {_id: 0}).min({"a": 0.5}).max({"a": 1.5}).toArray(),
- [{a: 1, b: 1}, {a: 1, b: 2}]);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+
+ assert.commandWorked(coll.insert({a: 1, b: 1}));
+ assert.commandWorked(coll.insert({a: 1, b: 2}));
+ assert.commandWorked(coll.insert({a: 2, b: 1}));
+ assert.commandWorked(coll.insert({a: 2, b: 2}));
+
+ // Throws error for $** index min.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), min: {"a": 0.5}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index max.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), max: {"a": 1.5}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index min/max.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), min: {"a": 0.5}, max: {"a": 1.5}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index min with filter of a different value.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 2}, min: {"a": 1}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index max with filter of a different value.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 1}, max: {"a": 1.5}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index min and max with filter of a different value.
+ assert.commandFailedWithCode(db.runCommand({
+ find: coll.getName(),
+ filter: {"a": 1},
+ min: {"a": 0.5},
+ max: {"a": 1.5},
+ hint: {"$**": 1}
+ }),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index min with filter of the same value.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 1}, min: {"a": 1}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index max with filter of the same value.
+ assert.commandFailedWithCode(
+ db.runCommand({find: coll.getName(), filter: {"a": 1}, max: {"a": 1}, hint: {"$**": 1}}),
+ ErrorCodes.BadValue);
+
+ // Throws error for $** index min and max with filter of the same value.
+ assert.commandFailedWithCode(db.runCommand({
+ find: coll.getName(),
+ filter: {"a": 1},
+ min: {"a": 1},
+ max: {"a": 1},
+ hint: {"$**": 1}
+ }),
+ ErrorCodes.BadValue);
+
+ assert.commandWorked(coll.createIndex({"a": 1}));
+
+ // $** index does not interfere with valid min/max.
+ assertArrayEq(coll.find({}, {_id: 0}).min({"a": 0.5}).max({"a": 1.5}).toArray(),
+ [{a: 1, b: 1}, {a: 1, b: 2}]);
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_multikey.js b/jstests/noPassthroughWithMongod/wildcard_index_multikey.js
index 7c5e7c93fea..d0887e810c9 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_multikey.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_multikey.js
@@ -101,152 +101,143 @@
}
}
- // Required in order to build $** indexes.
+ // Test a $** index that indexes the entire document.
+ runWildcardIndexTest({'$**': 1}, null, ['a', 'b.c', 'b.d.e']);
+ // Test a $** index on a single subtree.
+ runWildcardIndexTest({'a.$**': 1}, null, ['a']);
+ runWildcardIndexTest({'b.$**': 1}, null, ['b.c', 'b.d.e']);
+ runWildcardIndexTest({'b.c.$**': 1}, null, ['b.c']);
+ runWildcardIndexTest({'b.d.$**': 1}, null, ['b.d.e']);
+ // Test a $** index which includes a subset of paths.
+ runWildcardIndexTest({'$**': 1}, {a: 1}, ['a']);
+ runWildcardIndexTest({'$**': 1}, {b: 1}, ['b.c', 'b.d.e']);
+ runWildcardIndexTest({'$**': 1}, {'b.d': 1}, ['b.d.e']);
+ runWildcardIndexTest({'$**': 1}, {a: 1, 'b.d': 1}, ['a', 'b.d.e']);
+ // Test a $** index which excludes a subset of paths.
+ runWildcardIndexTest({'$**': 1}, {a: 0}, ['b.c', 'b.d.e']);
+ runWildcardIndexTest({'$**': 1}, {b: 0}, ['a']);
+ runWildcardIndexTest({'$**': 1}, {'b.c': 0}, ['a', 'b.d.e']);
+ runWildcardIndexTest({'$**': 1}, {a: 0, 'b.c': 0}, ['b.d.e']);
+
+ // Sanity check that a few queries which need to be planned specially in the multikey case
+ // return the correct results.
+ coll.drop();
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+ assert.commandWorked(coll.insert({a: [-5, 15]}));
+ assert.eq(1, coll.find({a: {$gt: 0, $lt: 9}}).itcount());
+ assert.eq(1, coll.find({a: {$gt: 0, $lt: 9}}).hint({$natural: 1}).itcount());
+ assert.eq(0, coll.find({a: {$elemMatch: {$gt: 0, $lt: 9}}}).itcount());
+ assert.eq(0, coll.find({a: {$elemMatch: {$gt: 0, $lt: 9}}}).hint({$natural: 1}).itcount());
+
+ assert.commandWorked(coll.insert({b: {c: {d: [{e: {f: -5}}, {e: {f: 15}}]}}}));
+ assert.eq(1, coll.find({"b.c.d.e.f": {$gt: 0, $lt: 9}}).itcount());
+ assert.eq(1, coll.find({"b.c.d.e.f": {$gt: 0, $lt: 9}}).hint({$natural: 1}).itcount());
+ assert.eq(0, coll.find({"b.c.d": {$elemMatch: {"e.f": {$gt: 0, $lt: 9}}}}).itcount());
+ assert.eq(0,
+ coll.find({"b.c.d": {$elemMatch: {"e.f": {$gt: 0, $lt: 9}}}})
+ .hint({$natural: 1})
+ .itcount());
+
+ // Fieldname-or-array-index query tests.
+ assert(coll.drop());
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+
+ // Insert some documents that exhibit a mix of numeric fieldnames and array indices.
+ assert.commandWorked(coll.insert({_id: 1, a: [{b: [{c: 1}]}]}));
+ assert.commandWorked(coll.insert({_id: 2, a: [{b: [{c: 0}, {c: 1}]}]}));
+ assert.commandWorked(coll.insert({_id: 3, a: {'0': [{b: {'1': {c: 1}}}, {d: 1}]}}));
+ assert.commandWorked(coll.insert({_id: 4, a: [{b: [{1: {c: 1}}]}]}));
assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- try {
- // Test a $** index that indexes the entire document.
- runWildcardIndexTest({'$**': 1}, null, ['a', 'b.c', 'b.d.e']);
- // Test a $** index on a single subtree.
- runWildcardIndexTest({'a.$**': 1}, null, ['a']);
- runWildcardIndexTest({'b.$**': 1}, null, ['b.c', 'b.d.e']);
- runWildcardIndexTest({'b.c.$**': 1}, null, ['b.c']);
- runWildcardIndexTest({'b.d.$**': 1}, null, ['b.d.e']);
- // Test a $** index which includes a subset of paths.
- runWildcardIndexTest({'$**': 1}, {a: 1}, ['a']);
- runWildcardIndexTest({'$**': 1}, {b: 1}, ['b.c', 'b.d.e']);
- runWildcardIndexTest({'$**': 1}, {'b.d': 1}, ['b.d.e']);
- runWildcardIndexTest({'$**': 1}, {a: 1, 'b.d': 1}, ['a', 'b.d.e']);
- // Test a $** index which excludes a subset of paths.
- runWildcardIndexTest({'$**': 1}, {a: 0}, ['b.c', 'b.d.e']);
- runWildcardIndexTest({'$**': 1}, {b: 0}, ['a']);
- runWildcardIndexTest({'$**': 1}, {'b.c': 0}, ['a', 'b.d.e']);
- runWildcardIndexTest({'$**': 1}, {a: 0, 'b.c': 0}, ['b.d.e']);
-
- // Sanity check that a few queries which need to be planned specially in the multikey case
- // return the correct results.
- coll.drop();
- assert.commandWorked(coll.createIndex({"$**": 1}));
- assert.commandWorked(coll.insert({a: [-5, 15]}));
- assert.eq(1, coll.find({a: {$gt: 0, $lt: 9}}).itcount());
- assert.eq(1, coll.find({a: {$gt: 0, $lt: 9}}).hint({$natural: 1}).itcount());
- assert.eq(0, coll.find({a: {$elemMatch: {$gt: 0, $lt: 9}}}).itcount());
- assert.eq(0, coll.find({a: {$elemMatch: {$gt: 0, $lt: 9}}}).hint({$natural: 1}).itcount());
-
- assert.commandWorked(coll.insert({b: {c: {d: [{e: {f: -5}}, {e: {f: 15}}]}}}));
- assert.eq(1, coll.find({"b.c.d.e.f": {$gt: 0, $lt: 9}}).itcount());
- assert.eq(1, coll.find({"b.c.d.e.f": {$gt: 0, $lt: 9}}).hint({$natural: 1}).itcount());
- assert.eq(0, coll.find({"b.c.d": {$elemMatch: {"e.f": {$gt: 0, $lt: 9}}}}).itcount());
- assert.eq(0,
- coll.find({"b.c.d": {$elemMatch: {"e.f": {$gt: 0, $lt: 9}}}})
- .hint({$natural: 1})
- .itcount());
-
- // Fieldname-or-array-index query tests.
- assert(coll.drop());
- assert.commandWorked(coll.createIndex({"$**": 1}));
-
- // Insert some documents that exhibit a mix of numeric fieldnames and array indices.
- assert.commandWorked(coll.insert({_id: 1, a: [{b: [{c: 1}]}]}));
- assert.commandWorked(coll.insert({_id: 2, a: [{b: [{c: 0}, {c: 1}]}]}));
- assert.commandWorked(coll.insert({_id: 3, a: {'0': [{b: {'1': {c: 1}}}, {d: 1}]}}));
- assert.commandWorked(coll.insert({_id: 4, a: [{b: [{1: {c: 1}}]}]}));
- assert.commandWorked(
- coll.insert({_id: 5, a: [{b: [{'1': {c: {'2': {d: [0, 1, 2, 3, {e: 1}]}}}}]}]}));
-
- /*
- * Multikey Metadata Keys:
- * {'': 1, '': 'a'}
- * {'': 1, '': 'a.0'}
- * {'': 1, '': 'a.b'}
- * {'': 1, '': 'a.b.1.c.2.d'}
- * Keys:
- * {'': 'a.b.c', '': 1} // _id: 1, a,b multikey
- * {'': 'a.b.c', '': 0} // _id: 2, a,b multikey
- * {'': 'a.b.c', '': 1} // _id: 2, a,b multikey
- * {'': 'a.0.b.1.c', '': 1} // _id: 3, '0, 1' are fieldnames, a.0 multikey
- * {'': 'a.0.d', '': 1} // _id: 3, '0' is fieldname, a.0 multikey
- * {'': 'a.b.1.c', '': 1} // _id: 4, '1' is fieldname, a,b multikey
- * {'': 'a.b.1.c.2.d', '': 0} // _id: 5, a,b,a.b.1.c.2.d multikey, '1' is fieldname
- * {'': 'a.b.1.c.2.d', '': 1} // _id: 5
- * {'': 'a.b.1.c.2.d', '': 2} // _id: 5
- * {'': 'a.b.1.c.2.d', '': 3} // _id: 5
- * {'': 'a.b.1.c.2.d.e', '': 1} // _id: 5
- */
-
- // Test that a query with multiple numeric path components returns all relevant documents,
- // whether the numeric path component refers to a fieldname or array index in each doc:
- //
- // _id:1 will be captured by the special fieldname-or-array-index bounds 'a.b.c', but will
- // be filtered out by the INEXACT_FETCH since it has no array index or fieldname 'b.1'.
- // _id:2 will match both 'a.0' and 'b.1' by array index.
- // _id:3 will match both 'a.0' and 'b.1' by fieldname.
- // _id:4 will match 'a.0' by array index and 'b.1' by fieldname.
- // _id:5 is not captured by the special fieldname-or-array-index bounds.
- //
- // We examine the solution's 'nReturned' versus 'totalDocsExamined' to confirm this.
- // totalDocsExamined: [_id:1, _id:2, _id:3, _id:4], nReturned: [_id:2, _id:3, _id:4]
- assertWildcardQuery({'a.0.b.1.c': 1},
- 'a.0.b.1.c',
- {'executionStats.nReturned': 3, 'executionStats.totalDocsExamined': 4});
-
- // Test that we can query a specific field of an array whose fieldname is itself numeric.
- assertWildcardQuery({'a.0.1.d': 1},
- 'a.0.1.d',
- {'executionStats.nReturned': 1, 'executionStats.totalDocsExamined': 1});
-
- // Test that we can query a primitive value at a specific array index.
- assertWildcardQuery({'a.0.b.1.c.2.d.3': 3},
- 'a.0.b.1.c.2.d.3',
- {'executionStats.nReturned': 1, 'executionStats.totalDocsExamined': 1});
-
- // Test that a $** index can't be used for a query through more than 8 nested array indices.
- assert.commandWorked(
- coll.insert({_id: 6, a: [{b: [{c: [{d: [{e: [{f: [{g: [{h: [{i: [1]}]}]}]}]}]}]}]}]}));
- // We can query up to a depth of 8 arrays via specific indices, but not through 9 or more.
- assertWildcardQuery({'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i': 1},
- 'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i');
- assertWildcardQuery({'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i.0': 1}, null);
-
- // Test that fieldname-or-array-index queries do not inappropriately trim predicates; that
- // is, all predicates on the field are added to a FETCH filter above the IXSCAN.
- assert(coll.drop());
- assert.commandWorked(coll.createIndex({"$**": 1}));
-
- assert.commandWorked(coll.insert({_id: 1, a: [0, 1, 2]}));
- assert.commandWorked(coll.insert({_id: 2, a: [1, 2, 3]}));
- assert.commandWorked(coll.insert({_id: 3, a: [2, 3, 4], b: [5, 6, 7]}));
- assert.commandWorked(coll.insert({_id: 4, a: [3, 4, 5], b: [6, 7, 8], c: {'0': 9}}));
- assert.commandWorked(coll.insert({_id: 5, a: [4, 5, 6], b: [7, 8, 9], c: {'0': 10}}));
- assert.commandWorked(coll.insert({_id: 6, a: [5, 6, 7], b: [8, 9, 10], c: {'0': 11}}));
-
- assertWildcardQuery({"a.0": {$gt: 1, $lt: 4}}, 'a.0', {'executionStats.nReturned': 2});
- assertWildcardQuery({"a.1": {$gte: 1, $lte: 4}}, 'a.1', {'executionStats.nReturned': 4});
- assertWildcardQuery({"b.2": {$in: [5, 9]}}, 'b.2', {'executionStats.nReturned': 1});
- assertWildcardQuery({"c.0": {$in: [10, 11]}}, 'c.0', {'executionStats.nReturned': 2});
-
- // Test that the $** index doesn't trim predicates when planning across multiple nested
- // $and/$or expressions on various fieldname-or-array-index paths.
- const trimTestQuery = {
- $or: [
- {"a.0": {$gte: 0, $lt: 3}, "a.1": {$in: [2, 3, 4]}},
- {"b.1": {$gt: 6, $lte: 9}, "c.0": {$gt: 9, $lt: 12}}
- ]
- };
- const trimTestExplain = coll.find(trimTestQuery).explain("executionStats");
- // Verify that the expected number of documents were matched, and the $** index was used.
- // Matched documents: [_id:2, _id:3, _id:5, _id:6]
- assert.eq(trimTestExplain.executionStats.nReturned, 4);
- const trimTestIxScans = getPlanStages(trimTestExplain.queryPlanner.winningPlan, "IXSCAN");
- for (let ixScan of trimTestIxScans) {
- assert.eq(ixScan.keyPattern["$_path"], 1);
- }
- // Finally, confirm that a collection scan produces the same results.
- assertArrayEq(coll.find(trimTestQuery).toArray(),
- coll.find(trimTestQuery).hint({$natural: 1}).toArray());
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false}));
+ coll.insert({_id: 5, a: [{b: [{'1': {c: {'2': {d: [0, 1, 2, 3, {e: 1}]}}}}]}]}));
+
+ /*
+ * Multikey Metadata Keys:
+ * {'': 1, '': 'a'}
+ * {'': 1, '': 'a.0'}
+ * {'': 1, '': 'a.b'}
+ * {'': 1, '': 'a.b.1.c.2.d'}
+ * Keys:
+ * {'': 'a.b.c', '': 1} // _id: 1, a,b multikey
+ * {'': 'a.b.c', '': 0} // _id: 2, a,b multikey
+ * {'': 'a.b.c', '': 1} // _id: 2, a,b multikey
+ * {'': 'a.0.b.1.c', '': 1} // _id: 3, '0, 1' are fieldnames, a.0 multikey
+ * {'': 'a.0.d', '': 1} // _id: 3, '0' is fieldname, a.0 multikey
+ * {'': 'a.b.1.c', '': 1} // _id: 4, '1' is fieldname, a,b multikey
+ * {'': 'a.b.1.c.2.d', '': 0} // _id: 5, a,b,a.b.1.c.2.d multikey, '1' is fieldname
+ * {'': 'a.b.1.c.2.d', '': 1} // _id: 5
+ * {'': 'a.b.1.c.2.d', '': 2} // _id: 5
+ * {'': 'a.b.1.c.2.d', '': 3} // _id: 5
+ * {'': 'a.b.1.c.2.d.e', '': 1} // _id: 5
+ */
+
+ // Test that a query with multiple numeric path components returns all relevant documents,
+ // whether the numeric path component refers to a fieldname or array index in each doc:
+ //
+ // _id:1 will be captured by the special fieldname-or-array-index bounds 'a.b.c', but will be
+ // filtered out by the INEXACT_FETCH since it has no array index or fieldname 'b.1'.
+ // _id:2 will match both 'a.0' and 'b.1' by array index.
+ // _id:3 will match both 'a.0' and 'b.1' by fieldname.
+ // _id:4 will match 'a.0' by array index and 'b.1' by fieldname.
+ // _id:5 is not captured by the special fieldname-or-array-index bounds.
+ //
+ // We examine the solution's 'nReturned' versus 'totalDocsExamined' to confirm this.
+ // totalDocsExamined: [_id:1, _id:2, _id:3, _id:4], nReturned: [_id:2, _id:3, _id:4]
+ assertWildcardQuery({'a.0.b.1.c': 1},
+ 'a.0.b.1.c',
+ {'executionStats.nReturned': 3, 'executionStats.totalDocsExamined': 4});
+
+ // Test that we can query a specific field of an array whose fieldname is itself numeric.
+ assertWildcardQuery({'a.0.1.d': 1},
+ 'a.0.1.d',
+ {'executionStats.nReturned': 1, 'executionStats.totalDocsExamined': 1});
+
+ // Test that we can query a primitive value at a specific array index.
+ assertWildcardQuery({'a.0.b.1.c.2.d.3': 3},
+ 'a.0.b.1.c.2.d.3',
+ {'executionStats.nReturned': 1, 'executionStats.totalDocsExamined': 1});
+
+ // Test that a $** index can't be used for a query through more than 8 nested array indices.
+ assert.commandWorked(
+ coll.insert({_id: 6, a: [{b: [{c: [{d: [{e: [{f: [{g: [{h: [{i: [1]}]}]}]}]}]}]}]}]}));
+ // We can query up to a depth of 8 arrays via specific indices, but not through 9 or more.
+ assertWildcardQuery({'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i': 1},
+ 'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i');
+ assertWildcardQuery({'a.0.b.0.c.0.d.0.e.0.f.0.g.0.h.0.i.0': 1}, null);
+
+ // Test that fieldname-or-array-index queries do not inappropriately trim predicates; that is,
+ // all predicates on the field are added to a FETCH filter above the IXSCAN.
+ assert(coll.drop());
+ assert.commandWorked(coll.createIndex({"$**": 1}));
+
+ assert.commandWorked(coll.insert({_id: 1, a: [0, 1, 2]}));
+ assert.commandWorked(coll.insert({_id: 2, a: [1, 2, 3]}));
+ assert.commandWorked(coll.insert({_id: 3, a: [2, 3, 4], b: [5, 6, 7]}));
+ assert.commandWorked(coll.insert({_id: 4, a: [3, 4, 5], b: [6, 7, 8], c: {'0': 9}}));
+ assert.commandWorked(coll.insert({_id: 5, a: [4, 5, 6], b: [7, 8, 9], c: {'0': 10}}));
+ assert.commandWorked(coll.insert({_id: 6, a: [5, 6, 7], b: [8, 9, 10], c: {'0': 11}}));
+
+ assertWildcardQuery({"a.0": {$gt: 1, $lt: 4}}, 'a.0', {'executionStats.nReturned': 2});
+ assertWildcardQuery({"a.1": {$gte: 1, $lte: 4}}, 'a.1', {'executionStats.nReturned': 4});
+ assertWildcardQuery({"b.2": {$in: [5, 9]}}, 'b.2', {'executionStats.nReturned': 1});
+ assertWildcardQuery({"c.0": {$in: [10, 11]}}, 'c.0', {'executionStats.nReturned': 2});
+
+ // Test that the $** index doesn't trim predicates when planning across multiple nested $and/$or
+ // expressions on various fieldname-or-array-index paths.
+ const trimTestQuery = {
+ $or: [
+ {"a.0": {$gte: 0, $lt: 3}, "a.1": {$in: [2, 3, 4]}},
+ {"b.1": {$gt: 6, $lte: 9}, "c.0": {$gt: 9, $lt: 12}}
+ ]
+ };
+ const trimTestExplain = coll.find(trimTestQuery).explain("executionStats");
+ // Verify that the expected number of documents were matched, and the $** index was used.
+ // Matched documents: [_id:2, _id:3, _id:5, _id:6]
+ assert.eq(trimTestExplain.executionStats.nReturned, 4);
+ const trimTestIxScans = getPlanStages(trimTestExplain.queryPlanner.winningPlan, "IXSCAN");
+ for (let ixScan of trimTestIxScans) {
+ assert.eq(ixScan.keyPattern["$_path"], 1);
}
+ // Finally, confirm that a collection scan produces the same results.
+ assertArrayEq(coll.find(trimTestQuery).toArray(),
+ coll.find(trimTestQuery).hint({$natural: 1}).toArray());
})();
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_nonblocking_sort.js b/jstests/noPassthroughWithMongod/wildcard_index_nonblocking_sort.js
index b9c7edb3921..09aaba0fd90 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_nonblocking_sort.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_nonblocking_sort.js
@@ -6,10 +6,6 @@
const coll = db.wildcard_nonblocking_sort;
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
assert.commandWorked(coll.createIndex({"$**": 1}, {wildcardProjection: {"excludedField": 0}}));
for (let i = 0; i < 50; i++) {
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_partial_index.js b/jstests/noPassthroughWithMongod/wildcard_index_partial_index.js
index 4e8d8ec090f..fe809c6030b 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_partial_index.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_partial_index.js
@@ -42,17 +42,9 @@
assert(isCollscan(db, explain.queryPlanner.winningPlan));
}
- try {
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
-
- testPartialWildcardIndex({"$**": 1}, {partialFilterExpression: {a: {$lte: 1.5}}});
-
- // Case where the partial filter expression is on a field not included in the index.
- testPartialWildcardIndex({"x.$**": 1}, {partialFilterExpression: {a: {$lte: 1.5}}});
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ // Case where the partial filter expression is on a field in the index.
+ testPartialWildcardIndex({"$**": 1}, {partialFilterExpression: {a: {$lte: 1.5}}});
+
+ // Case where the partial filter expression is on a field not included in the index.
+ testPartialWildcardIndex({"x.$**": 1}, {partialFilterExpression: {a: {$lte: 1.5}}});
})();
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_return_key.js b/jstests/noPassthroughWithMongod/wildcard_index_return_key.js
index 382aa9cfb98..7f8ed54e741 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_return_key.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_return_key.js
@@ -13,58 +13,48 @@
const assertArrayEq = (l, r) => assert(arrayEq(l, r), tojson(l) + " != " + tojson(r));
const assertArrayNotEq = (l, r) => assert(!arrayEq(l, r), tojson(l) + " == " + tojson(r));
- // Required in order to build $** indexes.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
+ assert.commandWorked(coll.createIndex({"$**": 1}));
- try {
- assert.commandWorked(coll.createIndex({"$**": 1}));
+ assert.commandWorked(coll.insert({a: 1, b: 2, c: {d: 2, e: 1}}));
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: {d: 1, e: 2}}));
+ assert.commandWorked(coll.insert({a: 2, b: 1, c: {d: 2, e: 2}}));
+ assert.commandWorked(coll.insert({a: 1, b: 1, c: {e: 2}}));
- assert.commandWorked(coll.insert({a: 1, b: 2, c: {d: 2, e: 1}}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: {d: 1, e: 2}}));
- assert.commandWorked(coll.insert({a: 2, b: 1, c: {d: 2, e: 2}}));
- assert.commandWorked(coll.insert({a: 1, b: 1, c: {e: 2}}));
+ // $** index return key with one field argument.
+ assertArrayEq(coll.find({a: 1}).returnKey().toArray(),
+ [{"$_path": "a", a: 1}, {"$_path": "a", a: 1}]);
- // $** index return key with one field argument.
- assertArrayEq(coll.find({a: 1}).returnKey().toArray(),
- [{"$_path": "a", a: 1}, {"$_path": "a", a: 1}]);
+ // $** index return key with dot path argument.
+ assertArrayEq(coll.find({"c.e": 1}).returnKey().toArray(), [{"$_path": "c.e", "c.e": 1}]);
- // $** index return key with dot path argument.
- assertArrayEq(coll.find({"c.e": 1}).returnKey().toArray(), [{"$_path": "c.e", "c.e": 1}]);
+ assert.commandWorked(coll.createIndex({"a": 1}));
- assert.commandWorked(coll.createIndex({"a": 1}));
+ // $** index return key with competing regular index.
+ assertArrayEq(coll.find({a: 1}).hint({"$**": 1}).returnKey().toArray(),
+ [{"$_path": "a", a: 1}, {"$_path": "a", a: 1}]);
- // $** index return key with competing regular index.
- assertArrayEq(coll.find({a: 1}).hint({"$**": 1}).returnKey().toArray(),
- [{"$_path": "a", a: 1}, {"$_path": "a", a: 1}]);
+ assert.commandWorked(coll.createIndex({"a": 1, "b": 1}));
- assert.commandWorked(coll.createIndex({"a": 1, "b": 1}));
+ // $** index return key with competing compound index.
+ assertArrayNotEq(coll.find({a: 1, b: 1}).hint({"$**": 1}).returnKey().toArray(),
+ [{a: 1, b: 1}]);
- // $** index return key with competing compound index.
- assertArrayNotEq(coll.find({a: 1, b: 1}).hint({"$**": 1}).returnKey().toArray(),
- [{a: 1, b: 1}]);
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}, f: [1, 2, 3]}));
+ assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}, g: [{h: 1}, {i: 2}]}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}, f: [1, 2, 3]}));
- assert.commandWorked(coll.insert({a: 2, b: 2, c: {e: 2}, g: [{h: 1}, {i: 2}]}));
+ // Multikey path $** index return key.
+ assertArrayEq(coll.find({f: 1}).returnKey().toArray(), [{"$_path": "f", f: 1}]);
- // Multikey path $** index return key.
- assertArrayEq(coll.find({f: 1}).returnKey().toArray(), [{"$_path": "f", f: 1}]);
+ // Multikey subobject $** index return key.
+ assertArrayEq(coll.find({"g.h": 1}).returnKey().toArray(), [{"$_path": "g.h", "g.h": 1}]);
- // Multikey subobject $** index return key.
- assertArrayEq(coll.find({"g.h": 1}).returnKey().toArray(), [{"$_path": "g.h", "g.h": 1}]);
+ assert.commandWorked(coll.dropIndexes());
+ assert.commandWorked(coll.createIndex({"c.$**": 1}));
- assert.commandWorked(coll.dropIndexes());
- assert.commandWorked(coll.createIndex({"c.$**": 1}));
+ // Path specified $** index return key.
+ assertArrayEq(coll.find({"c.d": 1}).returnKey().toArray(), [{"$_path": "c.d", "c.d": 1}]);
- // Path specified $** index return key.
- assertArrayEq(coll.find({"c.d": 1}).returnKey().toArray(), [{"$_path": "c.d", "c.d": 1}]);
-
- // Path specified $** index return key with irrelevant query. We expect this query to be
- // answered with a collection scan, in which case returnKey is expected to return empty
- // objects.
- assertArrayEq(coll.find({a: 1, b: 1}).returnKey().toArray(), [{}]);
- } finally {
- // Disable $** indexes once the tests have either completed or failed.
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: false});
- }
+ // Path specified $** index return key with irrelevant query. We expect this query to be
+ // answered with a COLLSCAN, in which case returnKey is expected to return empty objects.
+ assertArrayEq(coll.find({a: 1, b: 1}).returnKey().toArray(), [{}]);
})(); \ No newline at end of file
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_validindex.js b/jstests/noPassthroughWithMongod/wildcard_index_validindex.js
index eb3b92ba94e..6759a900762 100644
--- a/jstests/noPassthroughWithMongod/wildcard_index_validindex.js
+++ b/jstests/noPassthroughWithMongod/wildcard_index_validindex.js
@@ -30,138 +30,122 @@
1);
};
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
- try {
- // Can create a valid wildcard index.
- createIndexAndVerifyWithDrop({"$**": 1}, {name: kIndexName});
-
- // Can create a valid wildcard index with subpaths.
- createIndexAndVerifyWithDrop({"a.$**": 1}, {name: kIndexName});
-
- // Can create a wildcard index with partialFilterExpression.
- createIndexAndVerifyWithDrop({"$**": 1},
- {name: kIndexName, partialFilterExpression: {a: {"$gt": 0}}});
-
- // Can create a wildcard index with foreground & background construction.
- createIndexAndVerifyWithDrop({"$**": 1}, {background: false, name: kIndexName});
- createIndexAndVerifyWithDrop({"$**": 1}, {background: true, name: kIndexName});
-
- // Can create a wildcard index with index level collation.
- createIndexAndVerifyWithDrop({"$**": 1}, {collation: {locale: "fr"}, name: kIndexName});
-
- // Can create a wildcard index with an inclusion projection.
- createIndexAndVerifyWithDrop({"$**": 1},
- {wildcardProjection: {a: 1, b: 1, c: 1}, name: kIndexName});
- // Can create a wildcard index with an exclusion projection.
- createIndexAndVerifyWithDrop({"$**": 1},
- {wildcardProjection: {a: 0, b: 0, c: 0}, name: kIndexName});
- // Can include _id in an exclusion.
- createIndexAndVerifyWithDrop(
- {"$**": 1}, {wildcardProjection: {_id: 1, a: 0, b: 0, c: 0}, name: kIndexName});
- // Can exclude _id in an exclusion.
- createIndexAndVerifyWithDrop(
- {"$**": 1}, {wildcardProjection: {_id: 0, a: 1, b: 1, c: 1}, name: kIndexName});
-
- // Cannot create a wildcard index with a non-positive numeric key value.
- coll.dropIndexes();
- assert.commandFailedWithCode(coll.createIndex({"$**": 0}), ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": -1}), ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": -2}), ErrorCodes.CannotCreateIndex);
-
- // Cannot create a wildcard index with sparse option.
- assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {sparse: true}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a wildcard index with a v0 or v1 index.
- assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {v: 0}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {v: 1}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a unique index.
- assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {unique: true}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a hashed wildcard index.
- assert.commandFailedWithCode(coll.createIndex({"$**": "hashed"}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a TTL wildcard index.
- assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {expireAfterSeconds: 3600}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a geoSpatial wildcard index.
- assert.commandFailedWithCode(coll.createIndex({"$**": "2dsphere"}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": "2d"}), ErrorCodes.CannotCreateIndex);
-
- // Cannot create a text wildcard index using single sub-path syntax.
- assert.commandFailedWithCode(coll.createIndex({"a.$**": "text"}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot specify plugin by string.
- assert.commandFailedWithCode(coll.createIndex({"a": "wildcard"}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": "wildcard"}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create a compound wildcard index.
- assert.commandFailedWithCode(coll.createIndex({"$**": 1, "a": 1}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"a": 1, "$**": 1}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create an wildcard index with an invalid spec.
- assert.commandFailedWithCode(coll.createIndex({"a.$**.$**": 1}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**.$**": 1}),
- ErrorCodes.CannotCreateIndex);
- assert.commandFailedWithCode(coll.createIndex({"$**": "hello"}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot create an wildcard index with mixed inclusion exclusion.
- assert.commandFailedWithCode(
- createIndexHelper({"$**": 1}, {name: kIndexName, wildcardProjection: {a: 1, b: 0}}),
- 40178);
- // Cannot create an wildcard index with computed fields.
- assert.commandFailedWithCode(
- createIndexHelper({"$**": 1},
- {name: kIndexName, wildcardProjection: {a: 1, b: "string"}}),
- ErrorCodes.FailedToParse);
- // Cannot create an wildcard index with an empty projection.
- assert.commandFailedWithCode(
- createIndexHelper({"$**": 1}, {name: kIndexName, wildcardProjection: {}}),
- ErrorCodes.FailedToParse);
- // Cannot create another index type with "wildcardProjection" projection.
- assert.commandFailedWithCode(
- createIndexHelper({"a": 1}, {name: kIndexName, wildcardProjection: {a: 1, b: 1}}),
- ErrorCodes.BadValue);
- // Cannot create a text index with a "wildcardProjection" projection.
- assert.commandFailedWithCode(
- createIndexHelper({"$**": "text"},
- {name: kIndexName, wildcardProjection: {a: 1, b: 1}}),
- ErrorCodes.BadValue);
- // Cannot create an wildcard index with a non-object "wildcardProjection" projection.
- assert.commandFailedWithCode(
- createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: "string"}),
- ErrorCodes.TypeMismatch);
- // Cannot exclude an subfield of _id in an inclusion.
- assert.commandFailedWithCode(createIndexHelper({"_id.id": 0, a: 1, b: 1, c: 1}),
- ErrorCodes.CannotCreateIndex);
- // Cannot include an subfield of _id in an exclusion.
- assert.commandFailedWithCode(createIndexHelper({"_id.id": 1, a: 0, b: 0, c: 0}),
- ErrorCodes.CannotCreateIndex);
-
- // Cannot specify both a subpath and a projection.
- assert.commandFailedWithCode(
- createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: {a: 1}}),
- ErrorCodes.FailedToParse);
- assert.commandFailedWithCode(
- createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: {b: 0}}),
- ErrorCodes.FailedToParse);
- } finally {
- assert.commandWorked(
- db.adminCommand({"setParameter": 1, "internalQueryAllowAllPathsIndexes": false}));
- }
+ // Can create a valid wildcard index.
+ createIndexAndVerifyWithDrop({"$**": 1}, {name: kIndexName});
+
+ // Can create a valid wildcard index with subpaths.
+ createIndexAndVerifyWithDrop({"a.$**": 1}, {name: kIndexName});
+
+ // Can create a wildcard index with partialFilterExpression.
+ createIndexAndVerifyWithDrop({"$**": 1},
+ {name: kIndexName, partialFilterExpression: {a: {"$gt": 0}}});
+
+ // Can create a wildcard index with foreground & background construction.
+ createIndexAndVerifyWithDrop({"$**": 1}, {background: false, name: kIndexName});
+ createIndexAndVerifyWithDrop({"$**": 1}, {background: true, name: kIndexName});
+
+ // Can create a wildcard index with index level collation.
+ createIndexAndVerifyWithDrop({"$**": 1}, {collation: {locale: "fr"}, name: kIndexName});
+
+ // Can create a wildcard index with an inclusion projection.
+ createIndexAndVerifyWithDrop({"$**": 1},
+ {wildcardProjection: {a: 1, b: 1, c: 1}, name: kIndexName});
+ // Can create a wildcard index with an exclusion projection.
+ createIndexAndVerifyWithDrop({"$**": 1},
+ {wildcardProjection: {a: 0, b: 0, c: 0}, name: kIndexName});
+ // Can include _id in an exclusion.
+ createIndexAndVerifyWithDrop(
+ {"$**": 1}, {wildcardProjection: {_id: 1, a: 0, b: 0, c: 0}, name: kIndexName});
+ // Can exclude _id in an exclusion.
+ createIndexAndVerifyWithDrop(
+ {"$**": 1}, {wildcardProjection: {_id: 0, a: 1, b: 1, c: 1}, name: kIndexName});
+
+ // Cannot create a wildcard index with a non-positive numeric key value.
+ coll.dropIndexes();
+ assert.commandFailedWithCode(coll.createIndex({"$**": 0}), ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": -1}), ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": -2}), ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a wildcard index with sparse option.
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {sparse: true}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a wildcard index with a v0 or v1 index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {v: 0}),
+ ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {v: 1}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a unique index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {unique: true}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a hashed wildcard index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": "hashed"}), ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a TTL wildcard index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1}, {expireAfterSeconds: 3600}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a geoSpatial wildcard index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": "2dsphere"}),
+ ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": "2d"}), ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a text wildcard index using single sub-path syntax.
+ assert.commandFailedWithCode(coll.createIndex({"a.$**": "text"}), ErrorCodes.CannotCreateIndex);
+
+ // Cannot specify plugin by string.
+ assert.commandFailedWithCode(coll.createIndex({"a": "wildcard"}), ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": "wildcard"}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create a compound wildcard index.
+ assert.commandFailedWithCode(coll.createIndex({"$**": 1, "a": 1}),
+ ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"a": 1, "$**": 1}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot create an wildcard index with an invalid spec.
+ assert.commandFailedWithCode(coll.createIndex({"a.$**.$**": 1}), ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**.$**": 1}), ErrorCodes.CannotCreateIndex);
+ assert.commandFailedWithCode(coll.createIndex({"$**": "hello"}), ErrorCodes.CannotCreateIndex);
+
+ // Cannot create an wildcard index with mixed inclusion exclusion.
+ assert.commandFailedWithCode(
+ createIndexHelper({"$**": 1}, {name: kIndexName, wildcardProjection: {a: 1, b: 0}}), 40178);
+ // Cannot create an wildcard index with computed fields.
+ assert.commandFailedWithCode(
+ createIndexHelper({"$**": 1}, {name: kIndexName, wildcardProjection: {a: 1, b: "string"}}),
+ ErrorCodes.FailedToParse);
+ // Cannot create an wildcard index with an empty projection.
+ assert.commandFailedWithCode(
+ createIndexHelper({"$**": 1}, {name: kIndexName, wildcardProjection: {}}),
+ ErrorCodes.FailedToParse);
+ // Cannot create another index type with "wildcardProjection" projection.
+ assert.commandFailedWithCode(
+ createIndexHelper({"a": 1}, {name: kIndexName, wildcardProjection: {a: 1, b: 1}}),
+ ErrorCodes.BadValue);
+ // Cannot create a text index with a "wildcardProjection" projection.
+ assert.commandFailedWithCode(
+ createIndexHelper({"$**": "text"}, {name: kIndexName, wildcardProjection: {a: 1, b: 1}}),
+ ErrorCodes.BadValue);
+ // Cannot create an wildcard index with a non-object "wildcardProjection" projection.
+ assert.commandFailedWithCode(
+ createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: "string"}),
+ ErrorCodes.TypeMismatch);
+ // Cannot exclude an subfield of _id in an inclusion.
+ assert.commandFailedWithCode(createIndexHelper({"_id.id": 0, a: 1, b: 1, c: 1}),
+ ErrorCodes.CannotCreateIndex);
+ // Cannot include an subfield of _id in an exclusion.
+ assert.commandFailedWithCode(createIndexHelper({"_id.id": 1, a: 0, b: 0, c: 0}),
+ ErrorCodes.CannotCreateIndex);
+
+ // Cannot specify both a subpath and a projection.
+ assert.commandFailedWithCode(
+ createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: {a: 1}}),
+ ErrorCodes.FailedToParse);
+ assert.commandFailedWithCode(
+ createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: {b: 0}}),
+ ErrorCodes.FailedToParse);
})();
diff --git a/src/mongo/db/catalog/index_key_validate.cpp b/src/mongo/db/catalog/index_key_validate.cpp
index d8bda8fec86..f5b090b40a6 100644
--- a/src/mongo/db/catalog/index_key_validate.cpp
+++ b/src/mongo/db/catalog/index_key_validate.cpp
@@ -121,13 +121,6 @@ Status validateKeyPattern(const BSONObj& key, IndexDescriptor::IndexVersion inde
code, mongoutils::str::stream() << "Unknown index plugin '" << pluginName << '\'');
}
- if (pluginName == IndexNames::WILDCARD && !internalQueryAllowAllPathsIndexes.load()) {
- // TODO: SERVER-36198 remove this check once wildcard indexes are complete.
- return Status(
- ErrorCodes::NotImplemented,
- "Cannot use a wildcard index without enabling internalQueryAllowAllPathsIndexes");
- }
-
BSONObjIterator it(key);
while (it.more()) {
BSONElement keyElement = it.next();
diff --git a/src/mongo/db/catalog/index_key_validate_test.cpp b/src/mongo/db/catalog/index_key_validate_test.cpp
index 371cdc62633..1800e6d06d5 100644
--- a/src/mongo/db/catalog/index_key_validate_test.cpp
+++ b/src/mongo/db/catalog/index_key_validate_test.cpp
@@ -56,19 +56,14 @@ public:
TestCommandQueryKnobGuard() {
_prevEnabled = getTestCommandsEnabled();
setTestCommandsEnabled(true);
-
- _prevKnobEnabled = internalQueryAllowAllPathsIndexes.load();
- internalQueryAllowAllPathsIndexes.store(true);
}
~TestCommandQueryKnobGuard() {
setTestCommandsEnabled(_prevEnabled);
- internalQueryAllowAllPathsIndexes.store(_prevKnobEnabled);
}
private:
bool _prevEnabled;
- bool _prevKnobEnabled;
};
TEST(IndexKeyValidateTest, KeyElementValueOfSmallPositiveIntSucceeds) {
diff --git a/src/mongo/db/catalog/index_spec_validate_test.cpp b/src/mongo/db/catalog/index_spec_validate_test.cpp
index 9481460593c..32255f51ab3 100644
--- a/src/mongo/db/catalog/index_spec_validate_test.cpp
+++ b/src/mongo/db/catalog/index_spec_validate_test.cpp
@@ -68,21 +68,15 @@ public:
// TODO: Remove test command enabling/disabling in SERVER-36198
_prevEnabled = getTestCommandsEnabled();
setTestCommandsEnabled(true);
-
- // TODO: Remove knob enabling/disabling in SERVER-36198.
- _prevKnobEnabled = internalQueryAllowAllPathsIndexes.load();
- internalQueryAllowAllPathsIndexes.store(true);
}
~TestCommandFcvGuard() {
serverGlobalParams.featureCompatibility.setVersion(_prevVersion);
setTestCommandsEnabled(_prevEnabled);
- internalQueryAllowAllPathsIndexes.store(_prevKnobEnabled);
}
private:
bool _prevEnabled;
- bool _prevKnobEnabled;
ServerGlobalParams::FeatureCompatibility::Version _prevVersion;
};
diff --git a/src/mongo/db/query/query_knobs.cpp b/src/mongo/db/query/query_knobs.cpp
index 4d59a177c2e..403cc2ba873 100644
--- a/src/mongo/db/query/query_knobs.cpp
+++ b/src/mongo/db/query/query_knobs.cpp
@@ -116,6 +116,4 @@ MONGO_EXPORT_SERVER_PARAMETER(internalQueryPlannerGenerateCoveredWholeIndexScans
MONGO_EXPORT_SERVER_PARAMETER(internalQueryIgnoreUnknownJSONSchemaKeywords, bool, false);
MONGO_EXPORT_SERVER_PARAMETER(internalQueryProhibitBlockingMergeOnMongoS, bool, false);
-
-MONGO_EXPORT_SERVER_PARAMETER(internalQueryAllowAllPathsIndexes, bool, false);
} // namespace mongo
diff --git a/src/mongo/db/query/query_knobs.h b/src/mongo/db/query/query_knobs.h
index d7f6ab8d1c4..a7bc4a39bee 100644
--- a/src/mongo/db/query/query_knobs.h
+++ b/src/mongo/db/query/query_knobs.h
@@ -137,10 +137,4 @@ extern AtomicInt32 internalDocumentSourceCursorBatchSizeBytes;
extern AtomicInt32 internalDocumentSourceLookupCacheSizeBytes;
extern AtomicBool internalQueryProhibitBlockingMergeOnMongoS;
-
-//
-// In-progress features.
-//
-// TODO: Remove in SERVER-36198.
-extern AtomicBool internalQueryAllowAllPathsIndexes;
} // namespace mongo
diff --git a/src/mongo/dbtests/validate_tests.cpp b/src/mongo/dbtests/validate_tests.cpp
index ddc62bffc0e..f060ed785c1 100644
--- a/src/mongo/dbtests/validate_tests.cpp
+++ b/src/mongo/dbtests/validate_tests.cpp
@@ -66,9 +66,6 @@ public:
_db(nullptr) {
_client.createCollection(_ns);
{
- _origWildcardKnob = internalQueryAllowAllPathsIndexes.load();
- internalQueryAllowAllPathsIndexes.store(true);
-
AutoGetCollection autoGetCollection(&_opCtx, _nss, MODE_X);
_isInRecordIdOrder =
autoGetCollection.getCollection()->getRecordStore()->isInRecordIdOrder();
@@ -78,7 +75,6 @@ public:
~ValidateBase() {
_client.dropCollection(_ns);
getGlobalServiceContext()->unsetKillAllOperations();
- internalQueryAllowAllPathsIndexes.store(_origWildcardKnob);
}
protected:
@@ -140,7 +136,6 @@ protected:
unique_ptr<AutoGetDb> _autoDb;
Database* _db;
bool _isInRecordIdOrder;
- bool _origWildcardKnob{false};
};
template <bool full, bool background>
diff --git a/src/mongo/dbtests/wildcard_multikey_persistence_test.cpp b/src/mongo/dbtests/wildcard_multikey_persistence_test.cpp
index 6d31c903035..860fec6bec3 100644
--- a/src/mongo/dbtests/wildcard_multikey_persistence_test.cpp
+++ b/src/mongo/dbtests/wildcard_multikey_persistence_test.cpp
@@ -61,13 +61,10 @@ std::vector<InsertStatement> toInserts(std::vector<BSONObj> docs) {
class WildcardMultikeyPersistenceTestFixture : public unittest::Test {
public:
WildcardMultikeyPersistenceTestFixture() {
- _origWildcardKnob = internalQueryAllowAllPathsIndexes.load();
- internalQueryAllowAllPathsIndexes.store(true);
_opCtx = cc().makeOperationContext();
}
virtual ~WildcardMultikeyPersistenceTestFixture() {
- internalQueryAllowAllPathsIndexes.store(_origWildcardKnob);
_opCtx.reset();
}