|
As of version 3.0, this issue has been partially addressed. It's still the case that mongos will refuse to perform a non-multi update on a sharded collection if the query portion does not include an equality predicate on the shard key. However, the logic that detects for the presence of the shard key in the query portion has improved. SERVER-14973 added support for parsing the query predicate using the CanonicalQuery path, which applies some simple transformations to the query predicate (e.g. promoting expressions to the root of the tree if they are single child of an OR root or an AND root) before attempting to extract the value of the shard key.
See the shell snippet below, which shows a successful non-multi update on a sharded collection where the equality predicate on the shard key is wrapped inside a trivial OR:
mongos> sh.enableSharding("test")
|
{ "ok" : 1 }
|
mongos> sh.shardCollection("test.foo",{_id:"hashed"})
|
{ "collectionsharded" : "test.foo", "ok" : 1 }
|
mongos> db.foo.update({$or: [{_id: 5}]}, {$set: {a:1} }, {upsert:true} )
|
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 5 })
|
mongos> db.foo.find()
|
{ "_id" : 5, "a" : 1 }
|
But note that $in with a single-element array still does not pass. This will work once SERVER-12024 is resolved.
mongos> db.foo.update({_id: {$in: [6]}}, {$set: {a:1} }, {upsert:true} )
|
WriteResult({
|
"nMatched" : 0,
|
"nUpserted" : 0,
|
"nModified" : 0,
|
"writeError" : {
|
"code" : 61,
|
"errmsg" : "upsert { q: { _id: { $in: [ 6.0 ] } }, u: { $set: { a: 1.0 } }, multi: false, upsert: true } does not contain shard key for pattern { _id: \"hashed\" }"
|
}
|
})
|
|