summaryrefslogtreecommitdiff
path: root/jstests/sharding/agg_sort.js
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2017-08-28 15:10:42 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2017-09-01 15:36:35 -0400
commitbc3e230523e4677e2f3fed64ea89c369182a9272 (patch)
treebb35904e784f224e6d5ab87b508c69c72f447dd3 /jstests/sharding/agg_sort.js
parent4e01e3582541fc00ec2e83c97cac89b59fbfeb34 (diff)
downloadmongo-bc3e230523e4677e2f3fed64ea89c369182a9272.tar.gz
SERVER-30704 Use ARM to merge agg cursors on mongos.
Diffstat (limited to 'jstests/sharding/agg_sort.js')
-rw-r--r--jstests/sharding/agg_sort.js225
1 files changed, 225 insertions, 0 deletions
diff --git a/jstests/sharding/agg_sort.js b/jstests/sharding/agg_sort.js
new file mode 100644
index 00000000000..bd12565dd20
--- /dev/null
+++ b/jstests/sharding/agg_sort.js
@@ -0,0 +1,225 @@
+// 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(), 'shard0001');
+ 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.writeOK(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.writeOK(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();
+})();