summaryrefslogtreecommitdiff
path: root/jstests/aggregation/sort_key_with_missing_fields.js
blob: f70847c5f38bc21dd2434e9e7d9c5e1085455d5c (plain)
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
// Ensure that sort behavior for undefined, missing, and null fields is the same for both find and
// aggregation. This test validates the fix for SERVER-42565, which was caused by inconsistent
// behavior for generating sort keys in aggregation.
(function() {
"use strict";

const coll = db.sort_key_with_missing_fields;
coll.drop();

assert.commandWorked(coll.insert([
    {_id: 1, a: undefined},
    {_id: 2, a: null},
    {_id: 3, a: []},
    {_id: 4},
    {_id: 5},
    {_id: 6, a: []},
    {_id: 7, a: null},
    {_id: 8, a: undefined},
]));

// Correct ordering treats {a: undefined} and {a: []} as the same value (undefined) and treats {a:
// null} and missing "a" as the same value (null). When we sort by the "a" field, we expect the sort
// to put all the undefined-like documents in one group (1, 3, 6, 8) and all null-like documents in
// another (2, 4, 5, 7). We break the ties within these two groups by sorting on the "_id" field.
const expectedOrderForward = [1, 3, 6, 8, 2, 4, 5, 7];
const expectedOrderReverse = [...expectedOrderForward].reverse();

function getArrayOfIds(arrayOfDocs) {
    return arrayOfDocs.map(doc => doc._id);
}

function checkFindAndAggSorts(sortPattern, expectedOrder) {
    // We include the sort key in the projection so that it will be included in the diagnostic
    // output if the test fails as a result of incorrect output.
    const findResult =
        coll.find({}, {_id: 1, a: 1, key: {$meta: "sortKey"}}).sort(sortPattern).toArray();
    assert.eq(getArrayOfIds(findResult), expectedOrder, findResult);

    const aggResult =
        coll.aggregate({$sort: sortPattern}, {$addFields: {key: {$meta: "sortKey"}}}).toArray();
    assert.eq(getArrayOfIds(aggResult), expectedOrder, aggResult);
}

checkFindAndAggSorts({a: 1, _id: 1}, expectedOrderForward);
checkFindAndAggSorts({a: -1, _id: -1}, expectedOrderReverse);

// Repeat the above test, but this time we sort on a path that traverse an array, forcing the sort
// key generator to use its general path, instead of the fast path for sorting on non-array paths.
assert(coll.drop());
assert.commandWorked(coll.insert([
    {_id: 1, a: [{b: undefined}]},
    {_id: 2, a: [{b: null}]},
    {_id: 3, a: [{b: []}]},
    {_id: 4, a: [{}]},
    {_id: 5},
    {_id: 6, a: [{b: []}]},
    {_id: 7, a: [{b: null}]},
    {_id: 8, a: [{b: undefined}]},
]));

checkFindAndAggSorts({"a.b": 1, _id: 1}, expectedOrderForward);
checkFindAndAggSorts({"a.b": -1, _id: -1}, expectedOrderReverse);
}());