summaryrefslogtreecommitdiff
path: root/jstests/core/explain_distinct.js
blob: 37d5a48551626648e2089288f854fd6badcd8870 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
 * This test ensures that explain on the distinct command works.
 */
(function() {
    'use strict';

    load("jstests/libs/analyze_plan.js");

    var collName = "jstests_explain_distinct";
    var coll = db[collName];

    function runDistinctExplain(collection, keyString, query) {
        var distinctCmd = {
            distinct: collection.getName(),
            key: keyString
        };

        if (typeof query !== 'undefined') {
            distinctCmd.query = query;
        }

        return coll.runCommand({explain: distinctCmd, verbosity: 'executionStats'});
    }

    coll.drop();

    // Collection doesn't exist.
    var explain = runDistinctExplain(coll, 'a', {});
    assert.commandWorked(explain);
    assert(planHasStage(explain.queryPlanner.winningPlan, "EOF"));

    // Insert the data to perform distinct() on.
    for (var i = 0; i < 10; i++) {
        assert.writeOK(coll.insert({a: 1, b: 1}));
        assert.writeOK(coll.insert({a: 2, c: 1}));
    }

    assert.commandFailed(runDistinctExplain(coll, {}, {}));  // Bad keyString.
    assert.commandFailed(runDistinctExplain(coll, 'a', 'a'));  // Bad query.
    assert.commandFailed(runDistinctExplain(coll, 'b', {$not: 1}));  // Bad query.
    assert.commandFailed(runDistinctExplain(coll, 'a', {$not: 1}));  // Bad query.
    assert.commandFailed(runDistinctExplain(coll, '_id', {$not: 1}));  // Bad query.

    // Ensure that server accepts a distinct command with no 'query' field.
    assert.commandWorked(runDistinctExplain(coll, '', null));
    assert.commandWorked(runDistinctExplain(coll, ''));

    assert.eq([1], coll.distinct('b'));
    var explain = runDistinctExplain(coll, 'b', {});
    assert.commandWorked(explain);
    assert.eq(20, explain.executionStats.nReturned);
    assert(isCollscan(explain.queryPlanner.winningPlan));

    assert.commandWorked(coll.createIndex({a: 1}));

    assert.eq([1, 2], coll.distinct('a'));
    var explain = runDistinctExplain(coll, 'a', {});
    assert.commandWorked(explain);
    assert.eq(2, explain.executionStats.nReturned);
    assert(planHasStage(explain.queryPlanner.winningPlan, "PROJECTION"));
    assert(planHasStage(explain.queryPlanner.winningPlan, "DISTINCT_SCAN"));

    // Check that the DISTINCT_SCAN stage has the correct stats.
    var stage = getPlanStage(explain.queryPlanner.winningPlan, "DISTINCT_SCAN");
    assert.eq({a: 1}, stage.keyPattern);
    assert.eq("a_1", stage.indexName);
    assert.eq(false, stage.isMultiKey);
    assert.eq(false, stage.isUnique);
    assert.eq(false, stage.isSparse);
    assert.eq(false, stage.isPartial);
    assert.eq(1, stage.indexVersion);
    assert("indexBounds" in stage);

    assert.commandWorked(coll.createIndex({a: 1, b: 1}));

    assert.eq([1], coll.distinct('a', {a: 1}));
    var explain = runDistinctExplain(coll, 'a', {a: 1});
    assert.commandWorked(explain);
    assert.eq(1, explain.executionStats.nReturned);
    assert(planHasStage(explain.queryPlanner.winningPlan, "PROJECTION"));
    assert(planHasStage(explain.queryPlanner.winningPlan, "DISTINCT_SCAN"));

    assert.eq([1], coll.distinct('b', {a: 1}));
    var explain = runDistinctExplain(coll, 'b', {a: 1});
    assert.commandWorked(explain);
    assert.eq(10, explain.executionStats.nReturned);
    assert(planHasStage(explain.queryPlanner.winningPlan, "FETCH"));
    assert(isIxscan(explain.queryPlanner.winningPlan));
})();