mirror of https://github.com/mongodb/mongo
200 lines
5.9 KiB
JavaScript
200 lines
5.9 KiB
JavaScript
/**
|
|
* 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());
|