summaryrefslogtreecommitdiff
path: root/jstests/core/explain_sort_type.js
blob: df4d91c0bbf9c6208e7f25547585fecbd616c9a1 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
 * Test that explain reports the sort algorithm used for a blocking sort -- either "simple" or
 * "default".
 *
 * @tags: [
 *   # Shard filtering may be required if the collection is sharded, which could affect the query
 *   # planner's selection of the "simple" versus "default" sort algorithm.
 *   assumes_unsharded_collection,
 *   # This test uses a non-retryable multi-update command.
 *   requires_non_retryable_writes,
 * ]
 */
(function() {
"use strict";

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

const coll = db.explain_sort_type;
coll.drop();

let explain, sortStage;

assert.commandWorked(coll.insert({_id: 0, a: 1, b: 1}));
assert.commandWorked(coll.insert({_id: 1, a: 1, b: 2}));
assert.commandWorked(coll.insert({_id: 2, a: 1, b: 3}));
assert.commandWorked(coll.insert({_id: 3, a: 2, b: 1}));
assert.commandWorked(coll.insert({_id: 4, a: 2, b: 2}));
assert.commandWorked(coll.insert({_id: 5, a: 2, b: 3}));

// Without any indexes, the plan is to scan the collection and run a blocking SORT. This can use the
// simple sort algorithm.
assert.eq(
    [
        {_id: 0, a: 1, b: 1},
        {_id: 3, a: 2, b: 1},
        {_id: 1, a: 1, b: 2},
        {_id: 4, a: 2, b: 2},
        {_id: 2, a: 1, b: 3},
        {_id: 5, a: 2, b: 3}
    ],
    coll.find().sort({b: 1, a: 1}).toArray());
explain = coll.find().sort({b: 1, a: 1}).explain();
let winningPlan = getWinningPlan(explain.queryPlanner);
sortStage = getPlanStage(winningPlan, "SORT");
assert.neq(null, sortStage, explain);
assert.eq("simple", sortStage.type, explain);

// If sort key metadata is requested, then we still allow the "simple" algorithm.
assert.eq(
    [
        {_id: 0, a: 1, b: 1, key: [1, 1]},
        {_id: 3, a: 2, b: 1, key: [1, 2]},
        {_id: 1, a: 1, b: 2, key: [2, 1]},
        {_id: 4, a: 2, b: 2, key: [2, 2]},
        {_id: 2, a: 1, b: 3, key: [3, 1]},
        {_id: 5, a: 2, b: 3, key: [3, 2]}
    ],
    coll.find({}, {key: {$meta: "sortKey"}}).sort({b: 1, a: 1}).toArray());
explain = coll.find({}, {key: {$meta: "sortKey"}}).sort({b: 1, a: 1}).explain();
winningPlan = getWinningPlan(explain.queryPlanner);
sortStage = getPlanStage(winningPlan, "SORT");
assert.neq(null, sortStage, explain);
assert.eq("simple", sortStage.type, explain);

// When the blokcing sort is covered, operating on index key data, we use the "default" algorithm.
assert.commandWorked(coll.createIndex({a: 1, b: 1}));
assert.eq([{a: 1, b: 1}, {a: 2, b: 1}, {a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 2, b: 3}],
          coll.find({a: {$gt: 0}}, {_id: 0, a: 1, b: 1}).sort({b: 1, a: 1}).toArray());
explain = coll.find({a: {$gt: 0}}, {_id: 0, a: 1, b: 1}).sort({b: 1, a: 1}).explain();
// Verify that the plan involves an IXSCAN but no fetch.
winningPlan = getWinningPlan(explain.queryPlanner);
assert.neq(null, getPlanStage(winningPlan, "IXSCAN"), explain);
assert.eq(null, getPlanStage(winningPlan, "FETCH"), explain);
sortStage = getPlanStage(winningPlan, "SORT");
assert.neq(null, sortStage, explain);
assert.eq("default", sortStage.type, explain);

// If metadata other than "sortKey" is needed, then we fall back to the "default" algorithm. Here we
// show that when "textScore" metadata is attached to the documents in the result set, the sort uses
// the "default" algorithm.
assert.commandWorked(coll.createIndex({c: "text"}));
assert.commandWorked(coll.update({}, {$set: {c: "keyword"}}, {multi: true}));
assert.eq(
    [
        {a: 1, b: 1, score: 1.1},
        {a: 2, b: 1, score: 1.1},
        {a: 1, b: 2, score: 1.1},
        {a: 2, b: 2, score: 1.1},
        {a: 1, b: 3, score: 1.1},
        {a: 2, b: 3, score: 1.1}
    ],
    coll.find({$text: {$search: "keyword"}}, {_id: 0, a: 1, b: 1, score: {$meta: "textScore"}})
        .sort({b: 1, a: 1})
        .toArray());
explain =
    coll.find({$text: {$search: "keyword"}}, {_id: 0, a: 1, b: 1, score: {$meta: "textScore"}})
        .sort({b: 1, a: 1})
        .explain();
winningPlan = getWinningPlan(explain.queryPlanner);
sortStage = getPlanStage(winningPlan, "SORT");
assert.neq(null, sortStage, explain);
assert.eq("default", sortStage.type, explain);
}());