Files
mongo/jstests/sharding/query/agg_sort.js

220 lines
7.7 KiB
JavaScript

// Tests that the sort order is obeyed when an aggregation requests sorted results that are
// scattered across multiple shards.
(function() {
'use strict';
const shardingTest = new ShardingTest({shards: 2});
const db = shardingTest.getDB("test");
const coll = db.sharded_agg_sort;
coll.drop();
assert.commandWorked(shardingTest.s0.adminCommand({enableSharding: db.getName()}));
shardingTest.ensurePrimaryShard(db.getName(), shardingTest.shard1.shardName);
assert.commandWorked(
shardingTest.s0.adminCommand({shardCollection: coll.getFullName(), key: {_id: 1}}));
const nDocs = 10;
const yValues = [
"abc",
"ABC",
null,
1,
NumberLong(2),
NumberDecimal(-20),
MinKey,
MaxKey,
BinData(0, ""),
[3, 4],
];
const bulkOp = coll.initializeOrderedBulkOp();
for (var i = 0; i < nDocs; ++i) {
bulkOp.insert({_id: i, x: Math.floor(i / 2), y: yValues[i]});
}
assert.commandWorked(bulkOp.execute());
// Split the data into 3 chunks
assert.commandWorked(shardingTest.s0.adminCommand({split: coll.getFullName(), middle: {_id: 3}}));
assert.commandWorked(shardingTest.s0.adminCommand({split: coll.getFullName(), middle: {_id: 6}}));
// Migrate the middle chunk to another shard
assert.commandWorked(shardingTest.s0.adminCommand({
movechunk: coll.getFullName(),
find: {_id: 5},
to: shardingTest.getOther(shardingTest.getPrimaryShard(db.getName())).name
}));
function assertResultsEqual({actual, expected}) {
const resultsAsString = " actual: " + tojson(actual) + "\n expected: " + tojson(expected);
assert.eq(actual.length, expected.length, `different number of results:\n${resultsAsString}`);
for (let i = 0; i < actual.length; i++) {
assert.eq(actual[i], expected[i], `different results at index ${i}:\n${resultsAsString}`);
}
}
function testSorts() {
// Test a basic sort by _id.
assertResultsEqual({
actual: coll.aggregate([{$sort: {_id: 1}}]).toArray(),
expected: [
{_id: 0, x: 0, y: "abc"},
{_id: 1, x: 0, y: "ABC"},
{_id: 2, x: 1, y: null},
{_id: 3, x: 1, y: 1},
{_id: 4, x: 2, y: NumberLong(2)},
{_id: 5, x: 2, y: NumberDecimal(-20)},
{_id: 6, x: 3, y: MinKey},
{_id: 7, x: 3, y: MaxKey},
{_id: 8, x: 4, y: BinData(0, "")},
{_id: 9, x: 4, y: [3, 4]},
],
});
assertResultsEqual({
actual: coll.aggregate([{$sort: {_id: 1}}, {$project: {_id: 1}}]).toArray(),
expected: new Array(nDocs).fill().map(function(_, index) {
return {_id: index};
}),
});
// Test a compound sort.
assertResultsEqual({
actual: coll.aggregate([{$sort: {x: 1, y: 1}}]).toArray(),
expected: [
{_id: 1, x: 0, y: "ABC"},
{_id: 0, x: 0, y: "abc"},
{_id: 2, x: 1, y: null},
{_id: 3, x: 1, y: 1},
{_id: 5, x: 2, y: NumberDecimal(-20)},
{_id: 4, x: 2, y: NumberLong(2)},
{_id: 6, x: 3, y: MinKey},
{_id: 7, x: 3, y: MaxKey},
{_id: 9, x: 4, y: [3, 4]},
{_id: 8, x: 4, y: BinData(0, "")},
],
});
assertResultsEqual({
actual: coll.aggregate([{$sort: {x: 1, y: 1}}, {$project: {_id: 0, x: 1, y: 1}}]).toArray(),
expected: [
{x: 0, y: "ABC"},
{x: 0, y: "abc"},
{x: 1, y: null},
{x: 1, y: 1},
{x: 2, y: NumberDecimal(-20)},
{x: 2, y: NumberLong(2)},
{x: 3, y: MinKey},
{x: 3, y: MaxKey},
{x: 4, y: [3, 4]},
{x: 4, y: BinData(0, "")},
],
});
// Test a compound sort with a missing field.
assertResultsEqual({
actual: coll.aggregate({$sort: {missing: -1, x: 1, _id: -1}}).toArray(),
expected: [
{_id: 1, x: 0, y: "ABC"},
{_id: 0, x: 0, y: "abc"},
{_id: 3, x: 1, y: 1},
{_id: 2, x: 1, y: null},
{_id: 5, x: 2, y: NumberDecimal(-20)},
{_id: 4, x: 2, y: NumberLong(2)},
{_id: 7, x: 3, y: MaxKey},
{_id: 6, x: 3, y: MinKey},
{_id: 9, x: 4, y: [3, 4]},
{_id: 8, x: 4, y: BinData(0, "")},
]
});
}
testSorts();
assert.commandWorked(coll.createIndex({x: 1}));
testSorts();
assert.commandWorked(coll.createIndex({x: 1, y: 1}));
testSorts();
assert.commandWorked(coll.createIndex({missing: 1, x: -1}));
testSorts();
assert.commandWorked(coll.createIndex({missing: -1, x: 1, _id: -1}));
testSorts();
// Test that a sort including the text score is merged properly in a sharded cluster.
const textColl = db.sharded_agg_sort_text;
assert.commandWorked(
shardingTest.s0.adminCommand({shardCollection: textColl.getFullName(), key: {_id: 1}}));
assert.commandWorked(textColl.insert([
{_id: 0, text: "apple"},
{_id: 1, text: "apple orange banana apple"},
{_id: 2, text: "apple orange"},
{_id: 3, text: "apple orange banana apple apple banana"},
{_id: 4, text: "apple orange banana"},
{_id: 5, text: "apple orange banana apple apple"},
]));
// Split the data into 3 chunks
assert.commandWorked(
shardingTest.s0.adminCommand({split: textColl.getFullName(), middle: {_id: 2}}));
assert.commandWorked(
shardingTest.s0.adminCommand({split: textColl.getFullName(), middle: {_id: 4}}));
// Migrate the middle chunk to another shard
assert.commandWorked(shardingTest.s0.adminCommand({
movechunk: textColl.getFullName(),
find: {_id: 3},
to: shardingTest.getOther(shardingTest.getPrimaryShard(db.getName())).name
}));
assert.commandWorked(textColl.createIndex({text: "text"}));
assertResultsEqual({
actual: textColl
.aggregate([
{$match: {$text: {$search: "apple banana orange"}}},
{$sort: {x: {$meta: "textScore"}}}
])
.toArray(),
expected: [
{_id: 3, text: "apple orange banana apple apple banana"},
{_id: 5, text: "apple orange banana apple apple"},
{_id: 1, text: "apple orange banana apple"},
{_id: 4, text: "apple orange banana"},
{_id: 2, text: "apple orange"},
{_id: 0, text: "apple"},
],
});
function assertSortedByMetaField(results) {
for (let i = 0; i < results.length - 1; ++i) {
assert(results[i].hasOwnProperty("meta"),
`Expected all results to have "meta" field, found one without it at index ${i}`);
assert.gte(results[i].meta,
results[i + 1].meta,
`Expected results to be sorted by "meta" field, descending. Detected unsorted` +
` results at index ${i}, entire result set: ${tojson(results)}`);
}
}
assertSortedByMetaField(textColl
.aggregate([
{$match: {$text: {$search: "apple banana orange"}}},
{$sort: {x: {$meta: "textScore"}}},
{$project: {_id: 0, meta: {$meta: "textScore"}}},
])
.toArray());
assertSortedByMetaField(textColl
.aggregate([
{$match: {$text: {$search: "apple banana orange"}}},
{$project: {_id: 0, meta: {$meta: "textScore"}}},
{$sort: {meta: -1}},
])
.toArray());
assertSortedByMetaField(textColl
.aggregate([
{$sample: {size: 10}},
{$project: {_id: 0, meta: {$meta: "randVal"}}},
])
.toArray());
shardingTest.stop();
})();