From f24bfb54aa2eceea56557d4bddfb08e703ab74fa Mon Sep 17 00:00:00 2001 From: yarai Date: Tue, 18 Sep 2018 17:13:31 -0400 Subject: SERVER-35332 Index filter support for "allPaths" indexes --- .../wildcard_index_filter.js | 101 +++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 jstests/noPassthroughWithMongod/wildcard_index_filter.js (limited to 'jstests/noPassthroughWithMongod') 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 -- cgit v1.2.1