summaryrefslogtreecommitdiff
path: root/jstests/core/query/distinct/distinct_index1.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/core/query/distinct/distinct_index1.js')
-rw-r--r--jstests/core/query/distinct/distinct_index1.js84
1 files changed, 84 insertions, 0 deletions
diff --git a/jstests/core/query/distinct/distinct_index1.js b/jstests/core/query/distinct/distinct_index1.js
new file mode 100644
index 00000000000..75a7f8adc22
--- /dev/null
+++ b/jstests/core/query/distinct/distinct_index1.js
@@ -0,0 +1,84 @@
+/**
+ * Analyzes execution stats for indexed distinct.
+ * @tags: [
+ * assumes_balancer_off,
+ * assumes_read_concern_local,
+ * ]
+ */
+(function() {
+load("jstests/libs/analyze_plan.js"); // For getPlanStage.
+
+const coll = db.distinct_index1;
+coll.drop();
+
+function getHash(num) {
+ return Math.floor(Math.sqrt(num * 123123)) % 10;
+}
+
+function getDistinctExplainWithExecutionStats(field, query) {
+ const explain = coll.explain("executionStats").distinct(field, query || {});
+ assert(explain.hasOwnProperty("executionStats"), explain);
+ return explain;
+}
+
+const bulk = coll.initializeUnorderedBulkOp();
+for (let i = 0; i < 1000; i++) {
+ bulk.insert({a: getHash(i * 5), b: getHash(i)});
+}
+assert.commandWorked(bulk.execute());
+
+let explain = getDistinctExplainWithExecutionStats("a");
+// Collection scan looks at all 1000 documents and gets 1000 distinct values. Looks at 0 index
+// keys.
+assert.eq(1000, explain.executionStats.nReturned);
+assert.eq(0, explain.executionStats.totalKeysExamined);
+assert.eq(1000, explain.executionStats.totalDocsExamined);
+
+explain = getDistinctExplainWithExecutionStats("a", {a: {$gt: 5}});
+// Collection scan looks at all 1000 documents and gets 398 distinct values which match the
+// query. Looks at 0 index keys.
+assert.eq(398, explain.executionStats.nReturned);
+assert.eq(0, explain.executionStats.totalKeysExamined);
+assert.eq(1000, explain.executionStats.totalDocsExamined);
+
+explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}});
+// Collection scan looks at all 1000 documents and gets 398 distinct values which match the
+// query. Looks at 0 index keys.
+assert.eq(398, explain.executionStats.nReturned);
+assert.eq(0, explain.executionStats.totalKeysExamined);
+assert.eq(1000, explain.executionStats.totalDocsExamined);
+
+assert.commandWorked(coll.createIndex({a: 1}));
+
+explain = getDistinctExplainWithExecutionStats("a");
+// There are only 10 values. We use the fast distinct hack and only examine each value once.
+assert.eq(10, explain.executionStats.nReturned);
+assert.lte(10, explain.executionStats.totalKeysExamined);
+
+explain = getDistinctExplainWithExecutionStats("a", {a: {$gt: 5}});
+// Only 4 values of a are >= 5 and we use the fast distinct hack.
+assert.eq(4, explain.executionStats.nReturned);
+assert.eq(4, explain.executionStats.totalKeysExamined);
+assert.eq(0, explain.executionStats.totalDocsExamined);
+
+explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}});
+// We can't use the fast distinct hack here because we're distinct-ing over 'b'.
+assert.eq(398, explain.executionStats.nReturned);
+assert.eq(398, explain.executionStats.totalKeysExamined);
+assert.eq(398, explain.executionStats.totalDocsExamined);
+
+// Test that a distinct over a trailing field of the index can be covered.
+assert.commandWorked(coll.dropIndexes());
+assert.commandWorked(coll.createIndex({a: 1, b: 1}));
+explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}, b: {$gt: 5}});
+assert.lte(explain.executionStats.nReturned, 171);
+assert.eq(0, explain.executionStats.totalDocsExamined);
+
+// Should use an index scan over the hashed index.
+assert.commandWorked(coll.dropIndexes());
+assert.commandWorked(coll.createIndex({a: "hashed"}));
+explain = getDistinctExplainWithExecutionStats("a", {$or: [{a: 3}, {a: 5}]});
+assert.eq(188, explain.executionStats.nReturned);
+const indexScanStage = getPlanStage(getWinningPlan(explain.queryPlanner), "IXSCAN");
+assert.eq("hashed", indexScanStage.keyPattern.a);
+})();