summaryrefslogtreecommitdiff
path: root/jstests/sharding/merge_hashed_shard_key.js
blob: 86661c9c1b0811304af86d49e3b241590b576228 (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
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
// Tests that the $merge stage works correctly when the shard key is hashed. This includes the case
// when the "on" field is not explicitly specified and also when there is a unique, non-hashed index
// that matches the "on" field(s).
(function() {
"use strict";

load("jstests/aggregation/extras/merge_helpers.js");  // For withEachMergeMode,
                                                      // assertMergeFailsWithoutUniqueIndex,
// assertMergeSucceedsWithExpectedUniqueIndex.

const st = new ShardingTest({shards: 2, rs: {nodes: 1}, config: 1});

const mongosDB = st.s0.getDB("merge_hashed_shard_key");
const foreignDB = st.s0.getDB("merge_hashed_shard_key_foreign");
const source = mongosDB.source;
const target = mongosDB.target;
source.drop();
target.drop();

assert.commandWorked(source.insert({placeholderDoc: 1}));

function testHashedShardKey(shardKey, spec, prefixPipeline = []) {
    target.drop();
    st.shardColl(target, shardKey, spec);

    // Test that $merge passes without specifying an "on" field.
    assertMergeSucceedsWithExpectedUniqueIndex(
        {source: source, target: target, prevStages: prefixPipeline});

    // Test that $merge fails even if the "on" fields matches the shardKey, since it isn't
    // unique.
    assertMergeFailsWithoutUniqueIndex({
        source: source,
        target: target,
        onFields: Object.keys(shardKey),
        prevStages: prefixPipeline
    });

    // Test that the $merge passes if there exists a unique index prefixed on the hashed shard
    // key.
    const prefixedUniqueKey = Object.merge(shardKey, {extraField: 1});
    prefixPipeline = prefixPipeline.concat([{$addFields: {extraField: 1}}]);
    assert.commandWorked(target.createIndex(prefixedUniqueKey, {unique: true}));
    assertMergeSucceedsWithExpectedUniqueIndex(
        {source: source, target: target, prevStages: prefixPipeline});
    assertMergeSucceedsWithExpectedUniqueIndex({
        source: source,
        target: target,
        onFields: Object.keys(prefixedUniqueKey),
        prevStages: prefixPipeline
    });
}

//
// Tests for a hashed non-id shard key.
//
let prevStage = [{$addFields: {hashedKey: 1}}];
testHashedShardKey({hashedKey: 1}, {hashedKey: "hashed"}, prevStage);

//
// Tests for a hashed non-id dotted path shard key.
//
prevStage = [{$addFields: {dotted: {path: 1}}}];
testHashedShardKey({"dotted.path": 1}, {"dotted.path": "hashed"}, prevStage);

//
// Tests for a compound hashed shard key.
//
prevStage = [{$addFields: {hashedKey: {subField: 1}, nonHashedKey: 1}}];
testHashedShardKey({"hashedKey.subField": 1, nonHashedKey: 1},
                   {"hashedKey.subField": "hashed", nonHashedKey: 1},
                   prevStage);

//
// Tests for a hashed _id shard key.
//
target.drop();
st.shardColl(target, {_id: 1}, {_id: "hashed"});

// Test that $merge passes without specifying an "on" field.
assertMergeSucceedsWithExpectedUniqueIndex({source: source, target: target});

// Test that $merge passes when the uniqueKey matches the shard key. Note that the _id index is
// always create with {unique: true} regardless of whether the shard key was marked as unique
// when the collection was sharded.
assertMergeSucceedsWithExpectedUniqueIndex({source: source, target: target, uniqueKey: {_id: 1}});

st.stop();
})();