forked from mongodb/mongo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconcat_arrays.js
172 lines (155 loc) · 6.11 KB
/
concat_arrays.js
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
* Basic tests for the $concatArrays accumulator.
* @tags: [requires_fcv_81]
*/
import {assertErrorCode} from "jstests/aggregation/extras/utils.js";
const coll = db["accumulators_concat_arrays"];
assert(coll.drop());
// Test that $concatArrays correctly concatenates arrays, preserves sort order and preserves order
// of the elements inside the concatenated arrays.
assert.commandWorked(coll.insert([
{_id: 0, author: "Adrian", publisher: "Pub1", books: ["Adrian Book 0", "Adrian Book 1"]},
{_id: 1, author: "Militsa", publisher: "Pub1", books: ["Militsa Book 0"]},
{_id: 2, author: "Hana", publisher: "Pub1", books: ["Hana Book 0", "Hana Book 1"]},
]));
let result = coll.aggregate([
{$match: {_id: {$in: [0, 1, 2]}}},
{$sort: {_id: 1}},
{$group: {_id: null, allBooks: {$concatArrays: '$books'}}}
])
.toArray();
assert.eq(
result, [{
_id: null,
allBooks:
["Adrian Book 0", "Adrian Book 1", "Militsa Book 0", "Hana Book 0", "Hana Book 1"]
}]);
// Redo the aggregation with the reverse sort to ensure sort order is really preserverd and we're
// not just looking at the docs in the order they are found in the collection.
result = coll.aggregate([
{$match: {_id: {$in: [0, 1, 2]}}},
{$sort: {_id: -1}},
{$group: {_id: null, allBooks: {$concatArrays: '$books'}}}
])
.toArray();
assert.eq(
result, [{
_id: null,
allBooks:
["Hana Book 0", "Hana Book 1", "Militsa Book 0", "Adrian Book 0", "Adrian Book 1"]
}]);
// $concatArrays should concatenate arrays, and any nested arrays should remain array values.
assert.commandWorked(coll.insert({
_id: 3,
author: "Ben",
publisher: "Pub2",
books:
[["Ben Series 0 Book 0", "Ben Series 0 Book 1"], ["Ben Series 1 Book 0"], "Ben Book 4"]
}));
result = coll.aggregate([
{$match: {_id: {$in: [1, 3]}}},
{$sort: {_id: 1}},
{$group: {_id: null, allBooks: {$concatArrays: '$books'}}}
])
.toArray();
assert.eq(result, [{
_id: null,
allBooks: [
"Militsa Book 0",
["Ben Series 0 Book 0", "Ben Series 0 Book 1"],
["Ben Series 1 Book 0"],
"Ben Book 4"
]
}]);
// $concatArrays should 'skip over' documents that do not have field.
// Importantly, do not create a null element for documents that do not have the referenced field.
assert.commandWorked(coll.insert([
{_id: 4, author: "Nick", publisher: "Pub3", books: ["Smile :)"]},
{_id: 5, author: "Santiago", publisher: "Pub3"},
{_id: 6, author: "Matt", publisher: "Pub3", books: ["Happy!"]}
]));
result = coll.aggregate([
{$match: {_id: {$in: [4, 5, 6]}}},
{$sort: {_id: 1}},
{$group: {_id: null, allBooks: {$concatArrays: '$books'}}}
])
.toArray();
assert.eq(result, [{_id: null, allBooks: ["Smile :)", "Happy!"]}]);
// Test for errors on non-array types ($concatArrays only supports arrays).
const notArrays = [1, "string", {object: "object"}, null];
for (const notAnArray of notArrays) {
assert.commandWorked(coll.insert([{
_id: "doesNotMatter",
author: "doesNotMatter",
publisher: "doesNotMatter",
books: notAnArray
}]));
assertErrorCode(coll,
[{$group: {_id: null, allBooks: {$concatArrays: '$books'}}}],
ErrorCodes.TypeMismatch);
assert.commandWorked(coll.deleteOne({_id: "doesNotMatter"}));
}
// Basic test of $concatArrays with grouping.
result = coll.aggregate([
{$match: {_id: {$in: [0, 1, 3]}}},
{$sort: {_id: 1}},
{$group: {_id: '$publisher', booksByPublisher: {$concatArrays: '$books'}}},
{$sort: {_id: 1}}
])
.toArray();
assert.eq(result, [
{_id: "Pub1", booksByPublisher: ["Adrian Book 0", "Adrian Book 1", "Militsa Book 0"]},
{
_id: "Pub2",
booksByPublisher:
[["Ben Series 0 Book 0", "Ben Series 0 Book 1"], ["Ben Series 1 Book 0"], "Ben Book 4"]
},
]);
// $concatArrays dotted field.
assert(coll.drop());
assert.commandWorked(coll.insert(
[{_id: 1, a: {b: [1, 2, 3]}}, {_id: 2, a: {b: [4, 5, 6]}}, {_id: 3, a: {b: [7, 8, 9]}}]));
result = coll.aggregate([
{$sort: {_id: 1}},
{$group: {_id: null, nums: {$concatArrays: '$a.b'}}},
])
.toArray();
assert.eq(result, [{_id: null, nums: [1, 2, 3, 4, 5, 6, 7, 8, 9]}]);
assert(coll.drop());
// $concatArrays dotted field, array halfway on path.
assert(coll.drop());
assert.commandWorked(coll.insert([
{_id: 1, a: [{b: [1, 2, 3]}, {b: [4, 5, 6]}]},
{_id: 2, a: [{b: [7, 8, 9]}, {b: [10, 11, 12]}]},
{_id: 3, a: [{b: [7, 8, 9]}]}
]));
result = coll.aggregate([
{$sort: {_id: 1}},
{$group: {_id: null, nums: {$concatArrays: '$a.b'}}},
])
.toArray();
assert.eq(result, [{_id: null, nums: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [7, 8, 9]]}]);
assert(coll.drop());
// Basic correctness test for $concatArrays used in $bucket (see bucketAuto_concatArrays.js for
// $bucketAuto tests). Though $bucket and $bucketAuto use accumulators in the same way that $group
// does, the test below verifies that everything works properly with serialization and reporting
// results.
assert(coll.drop());
const docs = [];
for (let i = 0; i < 10; i++) {
docs.push({_id: i, arr: [i]});
}
coll.insertMany(docs);
result = coll.aggregate([
{$sort: {_id: 1}},
{
$bucket: {
groupBy: '$_id',
boundaries: [0, 5, 10],
output: {nums: {$concatArrays: "$arr"}}
}
}
])
.toArray();
assert.eq(result, [{"_id": 0, "nums": [0, 1, 2, 3, 4]}, {"_id": 5, "nums": [5, 6, 7, 8, 9]}]);
assert(coll.drop());