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
|
// Tests that the presence of an index does not impact the results of a mapReduce
// @tags: [
// # MR commands may not see previous inserts because MR does not support causal consistency so we
// # add this tag to exclude transactional passthroughs which commit versions in an ascynchronos
// # fashion and can cause stale reads.
// assumes_unsharded_collection,
// # mapReduce does not support afterClusterTime.
// does_not_support_causal_consistency,
// does_not_support_stepdowns,
// uses_map_reduce_with_temp_collections,
// ]
load("jstests/aggregation/extras/utils.js"); // For resultsEq
(function() {
"use strict";
const coll = db.mr_multikey_deduping;
coll.drop();
const outColl = db.mr_multikey_deduping_out;
outColl.drop();
(function testSingleKeyIndex() {
assert.commandWorked(coll.insert({arr: [1, 2]}));
const mapFn = function() {
emit(this._id, 1);
};
const reduceFn = function(k, vals) {
return Array.sum(vals);
};
let res = assert.commandWorked(
coll.mapReduce(mapFn, reduceFn, {out: {merge: outColl.getName()}, query: {}}));
assert(outColl.drop());
res = assert.commandWorked(coll.mapReduce(
mapFn, reduceFn, {out: {merge: outColl.getName()}, query: {arr: {$gte: 0}}}));
assert(outColl.drop());
// Now test that we get the same results when there's an index present.
assert.commandWorked(coll.createIndex({arr: 1}));
res = assert.commandWorked(coll.mapReduce(
mapFn, reduceFn, {out: {merge: outColl.getName()}, query: {arr: {$gte: 0}}}));
assert(outColl.drop());
}());
(function testCompoundIndex() {
coll.drop();
assert.commandWorked(coll.insert([
{_id: 1, name: 'name1', tags: ['dog', 'cat']},
{_id: 2, name: 'name2', tags: ['cat']},
{_id: 3, name: 'name3', tags: ['mouse', 'cat', 'dog']},
{_id: 4, name: 'name4', tags: []}
]));
const mapFn = function() {
for (var i = 0; i < this.tags.length; i++)
emit(this.tags[i], 1);
};
const reduceFn = function(key, values) {
return Array.sum(values);
};
const resultsNoIndexNoQuery =
assert
.commandWorked(db.runCommand(
{mapreduce: coll.getName(), map: mapFn, reduce: reduceFn, out: {inline: 1}}))
.results;
const resultsNoIndexEqualityOnName = assert
.commandWorked(db.runCommand({
mapreduce: coll.getName(),
map: mapFn,
reduce: reduceFn,
query: {name: 'name1'},
out: {inline: 1}
}))
.results;
const resultsNoIndexRangeOnName = assert
.commandWorked(db.runCommand({
mapreduce: coll.getName(),
map: mapFn,
reduce: reduceFn,
query: {name: {$gt: 'name'}},
out: {inline: 1}
}))
.results;
assert(resultsEq([{_id: "cat", value: 3}, {_id: "dog", value: 2}, {_id: "mouse", value: 1}],
resultsNoIndexNoQuery));
assert(
resultsEq([{_id: "cat", value: 1}, {_id: "dog", value: 1}], resultsNoIndexEqualityOnName));
assert(resultsEq(resultsNoIndexNoQuery, resultsNoIndexRangeOnName));
assert.commandWorked(coll.createIndex({name: 1, tags: 1}));
const resultsIndexedNoQuery =
assert
.commandWorked(db.runCommand(
{mapreduce: coll.getName(), map: mapFn, reduce: reduceFn, out: {inline: 1}}))
.results;
const resultsIndexedEqualityOnName = assert
.commandWorked(db.runCommand({
mapreduce: coll.getName(),
map: mapFn,
reduce: reduceFn,
query: {name: 'name1'},
out: {inline: 1}
}))
.results;
const resultsIndexedRangeOnName = assert
.commandWorked(db.runCommand({
mapreduce: coll.getName(),
map: mapFn,
reduce: reduceFn,
query: {name: {$gt: 'name'}},
out: {inline: 1}
}))
.results;
assert(resultsEq(resultsNoIndexNoQuery, resultsIndexedNoQuery));
assert(resultsEq(resultsNoIndexEqualityOnName, resultsIndexedEqualityOnName));
assert(resultsEq(resultsNoIndexRangeOnName, resultsIndexedRangeOnName));
}());
}());
|