确保分片集合中唯一字段的唯一性¶
概述¶
在创建索引时增加 unique 用来保证在一个 collection 中字段的唯一性.但是对于 分片集合这样的索引并不能保证字段的唯一性 ,因为插入和索引操作对于每个分片都是本地操作.
MongoDB does not support creating new unique indexes in sharded collections and will not allow you to shard collections with unique indexes on fields other than the _id field.
If you need to ensure that a field is always unique in a sharded collection, there are three options:
规程¶
片键上的唯一约束¶
过程¶
要使用 unique 条件进行分片,需要像下面这样执行 shardCollection :
db.runCommand( { shardCollection : "test.users" , key : { email : 1 } , unique : true } );
记住 _id 字段总是唯一的,默认情况下,MongoDB会将 ObjectId 写到 _id 字段.然而,你也可以将自己生成的值写到 _id 字段并用这个字段作为片键.使用以下操作将 _id 用作片键:
db.runCommand( { shardCollection : "test.users" } )
任意字段的唯一性.¶
如果不能使用片键保证唯一性或者要保证多个字段的唯一性,必须创建第二个 collection 作为 “代理集合”,代理集合需要包含对原始文档集合的引用(比如对 ObjectId 的引用),以及唯一字段.
如果必须在 “代理” 集合上分片,使用 上面的教程 用唯一字段做片键.如果不分片,可以直接在代理集合上创建多个唯一索引.
过程¶
参考以下使用”代理索引”的场景:
{
"_id" : ObjectId("...")
"email" ": "..."
}
_id 字段保存了主集合中的 ObjectId , email 字段是想要保证唯一性的字段.
要在代理集合分片,使用以下操作使用 email 字段做 shard key:
db.runCommand( { shardCollection : "records.proxy" ,
key : { email : 1 } ,
unique : true } );
如果不需要在代理集合分片,使用以下命令在 email 字段创建唯一索引:
db.proxy.createIndex( { "email" : 1 }, { unique : true } )
如果不需要在代理集合分片,可以在这个集合上创建多个唯一索引.
插入数据时,在 JavaScript shell: 中使用以下过程:
db = db.getSiblingDB('records');
var primary_id = ObjectId();
db.proxy.insert({
"_id" : primary_id
"email" : "example@example.net"
})
// if: the above operation returns successfully,
// then continue:
db.information.insert({
"_id" : primary_id
"email": "example@example.net"
// additional information...
})
必须首先在代理集合中插入一个数据,如果插入成功了,表明 email 字段是唯一的,之后就可以将其余的文档插入到 information 集合中.
参见
The full documentation of: createIndex() and shardCollection.
注意事项¶
你的应用必须能够捕获插入代理集合时产生的错误,并保证两个集合之前的一致性.
如果代理集合需要分片,必须使用你想要保证唯一性的字段做片键.
在对代理集合使用分片的情况下,如果想要保证多个字段的唯一性.必须对 每个保证唯一性的字段 都创建一个代理集合.如果使用一个代理集合用来确保多个字段的唯一性,这个代理集合 不能够 进行分片.
使用本身可以保证唯一性的标识符¶
保证唯一性最好的方法是创建自身可以保证唯一性的标识符(UUID),比如MongoDB的 ObjectId 值.
This approach is particularly useful for the``_id`` field, which must be unique: for collections where you are not sharding by the _id field the application is responsible for ensuring that the _id field is unique.