summaryrefslogtreecommitdiff
path: root/jstests/sharding/covered_shard_key_indexes.js
blob: 2926fea3b1bc70727c42871fa395e302f98e2d0d (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// Tests that indexes containing the shard key can be used without fetching the document for
// particular queries
//

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

(function() {
'use strict';

var st = new ShardingTest({shards: 1});
var coll = st.s0.getCollection("foo.bar");

assert.commandWorked(st.s0.adminCommand({enableSharding: coll.getDB() + ""}));

jsTest.log('Tests with _id : 1 shard key');
coll.drop();
assert.commandWorked(st.s0.adminCommand({shardCollection: coll + "", key: {_id: 1}}));
st.printShardingStatus();

assert.commandWorked(
    st.shard0.adminCommand({setParameter: 1, logComponentVerbosity: {query: {verbosity: 5}}}));

// Insert some data
assert.commandWorked(coll.insert({_id: true, a: true, b: true}));

// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({a: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({a: true}, {_id: 1, a: 1}).explain(true).executionStats.totalDocsExamined);

// Index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndexes());
assert.commandWorked(coll.ensureIndex({a: 1, _id: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0, coll.find({a: true}, {_id: 1, a: 1}).explain(true).executionStats.totalDocsExamined);

// Compound index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndexes());
assert.commandWorked(coll.ensureIndex({a: 1, b: 1, _id: 1}));
assert.eq(1, coll.find({a: true, b: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(
    0,
    coll.find({a: true, b: true}, {_id: 1, a: 1}).explain(true).executionStats.totalDocsExamined);

jsTest.log('Tests with _id : hashed shard key');
coll.drop();
assert.commandWorked(st.s0.adminCommand({shardCollection: coll + "", key: {_id: "hashed"}}));
st.printShardingStatus();

// Insert some data
assert.commandWorked(coll.insert({_id: true, a: true, b: true}));

// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({a: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({a: true}, {_id: 0, a: 1}).explain(true).executionStats.totalDocsExamined);

// Index with shard key query - can't be covered since hashed index
assert.commandWorked(coll.dropIndex({a: 1}));
assert.eq(1, coll.find({_id: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({_id: true}, {_id: 0}).explain(true).executionStats.totalDocsExamined);

jsTest.log('Tests with compound shard key');
coll.drop();
assert.commandWorked(st.s0.adminCommand({shardCollection: coll + "", key: {a: 1, b: 1}}));
st.printShardingStatus();

// Insert some data
assert.commandWorked(coll.insert({_id: true, a: true, b: true, c: true, d: true}));

// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({c: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1,
          coll.find({c: true}, {_id: 0, a: 1, b: 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

// Index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndex({c: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, b: 1, a: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0,
          coll.find({c: true}, {_id: 0, a: 1, b: 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

// Compound index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndex({c: 1, b: 1, a: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, d: 1, a: 1, b: 1, _id: 1}));
assert.eq(1, coll.find({c: true, d: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0,
          coll.find({c: true, d: true}, {a: 1, b: 1, c: 1, d: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

jsTest.log('Tests with nested shard key');
coll.drop();
assert.commandWorked(st.s0.adminCommand({shardCollection: coll + "", key: {'a.b': 1}}));
st.printShardingStatus();

// Insert some data
assert.commandWorked(coll.insert({_id: true, a: {b: true}, c: true}));

// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({c: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(
    1,
    coll.find({c: true}, {_id: 0, 'a.b': 1, c: 1}).explain(true).executionStats.totalDocsExamined);

// Index with shard key query - can be covered given the appropriate projection.
assert.commandWorked(coll.dropIndex({c: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, 'a.b': 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(
    0,
    coll.find({c: true}, {_id: 0, 'a.b': 1, c: 1}).explain(true).executionStats.totalDocsExamined);

jsTest.log('Tests with bad data with no shard key');
coll.drop();
assert.commandWorked(st.s0.adminCommand({shardCollection: coll + "", key: {a: 1}}));
st.printShardingStatus();

// Insert some bad data manually on the shard
assert.commandWorked(st.shard0.getCollection(coll.toString()).insert({_id: "bad data", c: true}));

// Index without shard key query - not covered but succeeds
assert.commandWorked(coll.ensureIndex({c: 1}));
var explain = coll.find({c: true}).explain(true).executionStats;
assert.eq(0, explain.nReturned);
assert.eq(1, explain.totalDocsExamined);
assert.eq(1, getChunkSkips(explain.executionStages.shards[0].executionStages));

// Index with shard key query - covered and succeeds and returns result
//
// NOTE: This is weird and only a result of the fact that we don't have a dedicated "does not
// exist" value for indexes
assert.commandWorked(coll.ensureIndex({c: 1, a: 1}));
var explain = coll.find({c: true}, {_id: 0, a: 1, c: 1}).explain(true).executionStats;
assert.eq(1, explain.nReturned);
assert.eq(0, explain.totalDocsExamined);
assert.eq(0, getChunkSkips(explain.executionStages.shards[0].executionStages));

st.stop();
})();