summaryrefslogtreecommitdiff
path: root/jstests/noPassthroughWithMongod
diff options
context:
space:
mode:
authoryarai <yuta.arai@10gen.com>2018-09-18 17:13:31 -0400
committeryarai <yuta.arai@10gen.com>2018-09-25 09:49:16 -0400
commitf24bfb54aa2eceea56557d4bddfb08e703ab74fa (patch)
treef683bc4e14ff56e7d08a2a041cf4703206adbd93 /jstests/noPassthroughWithMongod
parentfbeeccc651d7f88dea0ea36623470d3d46e615db (diff)
downloadmongo-f24bfb54aa2eceea56557d4bddfb08e703ab74fa.tar.gz
SERVER-35332 Index filter support for "allPaths" indexes
Diffstat (limited to 'jstests/noPassthroughWithMongod')
-rw-r--r--jstests/noPassthroughWithMongod/wildcard_index_filter.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/jstests/noPassthroughWithMongod/wildcard_index_filter.js b/jstests/noPassthroughWithMongod/wildcard_index_filter.js
new file mode 100644
index 00000000000..3cd0d535e91
--- /dev/null
+++ b/jstests/noPassthroughWithMongod/wildcard_index_filter.js
@@ -0,0 +1,101 @@
+/**
+ * Test that $** indexes obey index filter rules.
+ */
+(function() {
+ "use strict";
+
+ load("jstests/libs/analyze_plan.js");
+
+ const coll = db.wildcard_index_filter;
+
+ // Utility function to list index filters.
+ function getFilters() {
+ const res = assert.commandWorked(coll.runCommand('planCacheListFilters'));
+ assert(res.hasOwnProperty('filters'), 'filters missing from planCacheListFilters result');
+ return res.filters;
+ }
+
+ // Sets an index filter given a query shape then confirms that the expected index was used to
+ // answer a query.
+ function assertExpectedIndexAnswersQueryWithFilter(
+ filterQuery, filterIndexes, query, expectedIndexName, hint) {
+ // Clear existing cache filters.
+ assert.commandWorked(coll.runCommand('planCacheClearFilters'),
+ 'planCacheClearFilters failed');
+
+ // Make sure that the filter is set correctly.
+ assert.commandWorked(
+ coll.runCommand('planCacheSetFilter', {query: filterQuery, indexes: filterIndexes}));
+ assert.eq(1,
+ getFilters().length,
+ 'no change in query settings after successfully setting index filters');
+
+ // Check that expectedIndex index was used over another index.
+ let explain;
+ if (hint == undefined) {
+ explain = assert.commandWorked(coll.explain("executionStats").find(query).finish());
+ } else {
+ explain = assert.commandWorked(
+ coll.explain("executionStats").find(query).hint(hint).finish());
+ }
+
+ let planStage = getPlanStage(explain.executionStats.executionStages, 'IXSCAN');
+ assert.neq(null, planStage);
+ assert.eq(planStage.indexName, expectedIndexName, tojson(planStage));
+ }
+
+ // Required in order to build $** indexes.
+ assert.commandWorked(
+ db.adminCommand({setParameter: 1, internalQueryAllowAllPathsIndexes: true}));
+
+ try {
+ const indexWildcard = {"$**": 1};
+ const indexA = {"a": 1};
+ assert.commandWorked(coll.createIndex(indexWildcard));
+ assert.commandWorked(coll.createIndex(indexA));
+
+ assert.commandWorked(coll.insert({a: "a"}));
+
+ // 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");
+
+ assert.commandWorked(coll.insert({a: "a", b: "b"}));
+
+ 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 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 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);
+
+ 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}));
+ }
+})(); \ No newline at end of file