279 lines
12 KiB
JavaScript
279 lines
12 KiB
JavaScript
//
|
|
// This checks to make sure that sharded regex queries behave the same as unsharded regex queries
|
|
// @tags : [ hashed ]
|
|
//
|
|
|
|
var options = { mongosOptions : { binVersion : "" },
|
|
shardOptions : { binVersion : "" },
|
|
configOptions : { binVersion : "" } };
|
|
|
|
var st = new ShardingTest({ shards : 2, other : options });
|
|
st.stopBalancer();
|
|
|
|
var mongos = st.s0;
|
|
var admin = mongos.getDB("admin");
|
|
var shards = mongos.getDB("config").shards.find().toArray();
|
|
|
|
//
|
|
// Set up multiple collections to target with regex shard keys on two shards
|
|
//
|
|
|
|
var coll = mongos.getCollection("foo.bar");
|
|
var collSharded = mongos.getCollection("foo.barSharded");
|
|
var collCompound = mongos.getCollection("foo.barCompound");
|
|
var collNested = mongos.getCollection("foo.barNested");
|
|
var collHashed = mongos.getCollection("foo.barHashed");
|
|
|
|
assert.commandWorked(admin.runCommand({ enableSharding : coll.getDB().toString() }));
|
|
admin.runCommand({ movePrimary : coll.getDB().toString(), to : shards[0]._id });
|
|
|
|
//
|
|
// Split the collection so that "abcde-0" and "abcde-1" go on different shards when possible
|
|
//
|
|
|
|
assert.commandWorked(admin.runCommand({ shardCollection : collSharded.toString(),
|
|
key: { a : 1 } }));
|
|
assert.commandWorked(admin.runCommand({ split : collSharded.toString(),
|
|
middle : { a : "abcde-1" } }));
|
|
assert.commandWorked(admin.runCommand({ moveChunk : collSharded.toString(),
|
|
find : { a : 0 },
|
|
to : shards[1]._id,
|
|
_waitForDelete : true }));
|
|
|
|
assert.commandWorked(admin.runCommand({ shardCollection : collCompound.toString(),
|
|
key: { a : 1, b : 1 } }));
|
|
assert.commandWorked(admin.runCommand({ split : collCompound.toString(),
|
|
middle : { a : "abcde-1", b : 0 } }));
|
|
assert.commandWorked(admin.runCommand({ moveChunk : collCompound.toString(),
|
|
find : { a : 0, b : 0 },
|
|
to : shards[1]._id,
|
|
_waitForDelete : true }));
|
|
|
|
assert.commandWorked(admin.runCommand({ shardCollection : collNested.toString(),
|
|
key : { 'a.b' : 1 } }));
|
|
assert.commandWorked(admin.runCommand({ split : collNested.toString(),
|
|
middle : { 'a.b' : "abcde-1" } }));
|
|
assert.commandWorked(admin.runCommand({ moveChunk : collNested.toString(),
|
|
find : { a : { b : 0 } },
|
|
to : shards[1]._id,
|
|
_waitForDelete : true }));
|
|
|
|
assert.commandWorked(admin.runCommand({ shardCollection : collHashed.toString(),
|
|
key: { hash : "hashed" } }));
|
|
|
|
st.printShardingStatus();
|
|
|
|
//
|
|
//
|
|
// Cannot insert regex _id
|
|
assert.writeError(coll.insert({ _id : /regex value/ }));
|
|
assert.writeError(collSharded.insert({ _id : /regex value/, a : 0 }));
|
|
assert.writeError(collCompound.insert({ _id : /regex value/, a : 0, b : 0 }));
|
|
assert.writeError(collNested.insert({ _id : /regex value/, a : { b : 0 } }));
|
|
assert.writeError(collHashed.insert({ _id : /regex value/, hash : 0 }));
|
|
|
|
|
|
//
|
|
//
|
|
// (For now) we can insert a regex shard key
|
|
assert.writeOK(collSharded.insert({ a : /regex value/ }));
|
|
assert.writeOK(collCompound.insert({ a : /regex value/, b : "other value" }));
|
|
assert.writeOK(collNested.insert({ a : { b : /regex value/ } }));
|
|
assert.writeOK(collHashed.insert({ hash : /regex value/ }));
|
|
|
|
|
|
//
|
|
//
|
|
// Query by regex should hit all matching keys, across all shards if applicable
|
|
coll.remove({});
|
|
assert.writeOK(coll.insert({ a : "abcde-0" }));
|
|
assert.writeOK(coll.insert({ a : "abcde-1" }));
|
|
assert.writeOK(coll.insert({ a : /abcde.*/ }));
|
|
assert.eq(coll.find().itcount(), coll.find({ a : /abcde.*/ }).itcount());
|
|
|
|
collSharded.remove({});
|
|
assert.writeOK(collSharded.insert({ a : "abcde-0" }));
|
|
assert.writeOK(collSharded.insert({ a : "abcde-1" }));
|
|
assert.writeOK(collSharded.insert({ a : /abcde.*/ }));
|
|
assert.eq(collSharded.find().itcount(), collSharded.find({ a : /abcde.*/ }).itcount());
|
|
|
|
collCompound.remove({});
|
|
assert.writeOK(collCompound.insert({ a : "abcde-0", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : "abcde-1", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : /abcde.*/, b : 0 }));
|
|
assert.eq(collCompound.find().itcount(), collCompound.find({ a : /abcde.*/ }).itcount());
|
|
|
|
collNested.remove({});
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-0" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-1" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : /abcde.*/ } }));
|
|
assert.eq(collNested.find().itcount(), collNested.find({ 'a.b' : /abcde.*/ }).itcount());
|
|
|
|
collHashed.remove({});
|
|
while (st.shard0.getCollection(collHashed.toString()).count() == 0 ||
|
|
st.shard1.getCollection(collHashed.toString()).count() == 0) {
|
|
assert.writeOK(collHashed.insert({ hash : "abcde-" + ObjectId().toString() }));
|
|
}
|
|
assert.writeOK(collHashed.insert({ hash : /abcde.*/ }));
|
|
assert.eq(collHashed.find().itcount(), collHashed.find({ hash : /abcde.*/ }).itcount());
|
|
|
|
|
|
//
|
|
//
|
|
// Update by regex should hit all matching keys, across all shards if applicable
|
|
coll.remove({});
|
|
assert.writeOK(coll.insert({ a : "abcde-0" }));
|
|
assert.writeOK(coll.insert({ a : "abcde-1" }));
|
|
assert.writeOK(coll.insert({ a : /abcde.*/ }));
|
|
assert.writeOK(coll.update({ a : /abcde.*/ },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(coll.find().itcount(), coll.find({ updated : true }).itcount());
|
|
|
|
collSharded.remove({});
|
|
assert.writeOK(collSharded.insert({ a : "abcde-0" }));
|
|
assert.writeOK(collSharded.insert({ a : "abcde-1" }));
|
|
assert.writeOK(collSharded.insert({ a : /abcde.*/ }));
|
|
assert.writeOK(collSharded.update({ a : /abcde.*/ },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(collSharded.find().itcount(), collSharded.find({ updated : true }).itcount());
|
|
|
|
collCompound.remove({});
|
|
assert.writeOK(collCompound.insert({ a : "abcde-0", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : "abcde-1", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : /abcde.*/, b : 0 }));
|
|
assert.writeOK(collCompound.update({ a : /abcde.*/ },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(collCompound.find().itcount(), collCompound.find({ updated : true }).itcount());
|
|
|
|
collNested.remove({});
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-0" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-1" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : /abcde.*/ } }));
|
|
assert.writeOK(collNested.update({ 'a.b' : /abcde.*/ },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(collNested.find().itcount(), collNested.find({ updated : true }).itcount());
|
|
|
|
collHashed.remove({});
|
|
while (st.shard0.getCollection(collHashed.toString()).count() == 0 ||
|
|
st.shard1.getCollection(collHashed.toString()).count() == 0) {
|
|
assert.writeOK(collHashed.insert({ hash : "abcde-" + ObjectId().toString() }));
|
|
}
|
|
assert.writeOK(collHashed.insert({ hash : /abcde.*/ }));
|
|
assert.writeOK(collHashed.update({ hash : /abcde.*/ },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(collHashed.find().itcount(), collHashed.find({ updated : true }).itcount());
|
|
|
|
//
|
|
//
|
|
// Upsert with op-style regex should fail on sharded collections
|
|
// Query clause is targeted, and regex in query clause is ambiguous
|
|
collSharded.remove({});
|
|
collCompound.remove({});
|
|
collNested.remove({});
|
|
assert.writeError(collSharded.update({ a : /abcde.*/ }, { $set : { a : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
assert.writeError(collCompound.update({ a : /abcde.*/ }, { $set : { a : /abcde.*/, b : 1 } },
|
|
{ upsert : true }));
|
|
// Exact regex in query never equality
|
|
assert.writeError(collNested.update({ 'a.b' : /abcde.*/ }, { $set : { 'a.b' : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
// Even nested regexes are not extracted in queries
|
|
assert.writeError(collNested.update({ a : { b : /abcde.*/ } }, { $set : { 'a.b' : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
assert.writeError(collNested.update({ c : 1 }, { $set : { 'a.b' : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
|
|
//
|
|
//
|
|
// Upsert by replacement-style regex should succeed on sharded collections
|
|
// Replacement clause is targeted, and regex is unambiguously a value
|
|
collSharded.remove({});
|
|
collCompound.remove({});
|
|
collNested.remove({});
|
|
assert.writeOK(collSharded.update({ a : /abcde.*/ }, { a : /abcde.*/ }, { upsert : true }));
|
|
assert.writeOK(collCompound.update({ a : /abcde.*/ }, { a : /abcde.*/, b : 1 }, { upsert : true }));
|
|
assert.writeOK(collNested.update({ 'a.b' : /abcde.*/ }, { a : { b : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
assert.writeOK(collNested.update({ a : { b : /abcde.*/ } }, { a : { b : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
assert.writeOK(collNested.update({ c : 1 }, { a : { b : /abcde.*/ } },
|
|
{ upsert : true }));
|
|
|
|
//
|
|
//
|
|
// Remove by regex should hit all matching keys, across all shards if applicable
|
|
coll.remove({});
|
|
assert.writeOK(coll.insert({ a : "abcde-0" }));
|
|
assert.writeOK(coll.insert({ a : "abcde-1" }));
|
|
assert.writeOK(coll.insert({ a : /abcde.*/ }));
|
|
assert.writeOK(coll.remove({ a : /abcde.*/ }));
|
|
assert.eq(0, coll.find({}).itcount());
|
|
|
|
|
|
collSharded.remove({});
|
|
assert.writeOK(collSharded.insert({ a : "abcde-0" }));
|
|
assert.writeOK(collSharded.insert({ a : "abcde-1" }));
|
|
assert.writeOK(collSharded.insert({ a : /abcde.*/ }));
|
|
assert.writeOK(collSharded.remove({ a : /abcde.*/ }));
|
|
assert.eq(0, collSharded.find({}).itcount());
|
|
|
|
collCompound.remove({});
|
|
assert.writeOK(collCompound.insert({ a : "abcde-0", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : "abcde-1", b : 0 }));
|
|
assert.writeOK(collCompound.insert({ a : /abcde.*/, b : 0 }));
|
|
assert.writeOK(collCompound.remove({ a : /abcde.*/ }));
|
|
assert.eq(0, collCompound.find({}).itcount());
|
|
|
|
collNested.remove({});
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-0" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-1" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : /abcde.*/ } }));
|
|
assert.writeOK(collNested.remove({ 'a.b' : /abcde.*/ }));
|
|
assert.eq(0, collNested.find({}).itcount());
|
|
|
|
collHashed.remove({});
|
|
while (st.shard0.getCollection(collHashed.toString()).count() == 0 ||
|
|
st.shard1.getCollection(collHashed.toString()).count() == 0) {
|
|
assert.writeOK(collHashed.insert({ hash : "abcde-" + ObjectId().toString() }));
|
|
}
|
|
assert.writeOK(collHashed.insert({ hash : /abcde.*/ }));
|
|
assert.writeOK(collHashed.remove({ hash : /abcde.*/ }));
|
|
assert.eq(0, collHashed.find({}).itcount());
|
|
|
|
|
|
//
|
|
//
|
|
// Query/Update/Remove by nested regex is different depending on how the nested regex is specified
|
|
coll.remove({});
|
|
assert.writeOK(coll.insert({ a : { b : "abcde-0" } }));
|
|
assert.writeOK(coll.insert({ a : { b : "abcde-1" } }));
|
|
assert.writeOK(coll.insert({ a : { b : /abcde.*/ } }));
|
|
assert.eq(1, coll.find({ a : { b : /abcde.*/ } }).itcount());
|
|
assert.writeOK(coll.update({ a : { b : /abcde.*/ } },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(1, coll.find({ updated : true }).itcount());
|
|
assert.writeOK(coll.remove({ a : { b : /abcde.*/ } }));
|
|
assert.eq(2, coll.find().itcount());
|
|
|
|
collNested.remove({});
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-0" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : "abcde-1" } }));
|
|
assert.writeOK(collNested.insert({ a : { b : /abcde.*/ } }));
|
|
assert.eq(1, collNested.find({ a : { b : /abcde.*/ } }).itcount());
|
|
assert.writeOK(collNested.update({ a : { b : /abcde.*/ } },
|
|
{ $set : { updated : true } },
|
|
{ multi : true }));
|
|
assert.eq(1, collNested.find({ updated : true }).itcount());
|
|
assert.writeOK(collNested.remove({ a : { b : /abcde.*/ } }));
|
|
assert.eq(2, collNested.find().itcount());
|
|
|
|
jsTest.log("DONE!");
|
|
st.stop();
|
|
|