如果无法使用唯一字段作为分片键,或者需要实施多个字段的唯一性,请创建另一个集合以充当代理集合。
关于此任务
仅当唯一索引位于分片键上或包含分片键作为前缀时,分片集群才会跨分片实施唯一约束。代理集合可以绕过该限制:代理集合包含对原始文档的引用和唯一键,并且您的应用程序会首先写入代理集合。
使用代理集合时,请考虑以下事项:
在将文档插入代理集合时,应用程序必须捕获错误,并且必须实施两个集合之间的一致性。
如果代理集合需要分片,则必须对要强制唯一性的单个字段进行分片。
每个字段都需要自己的代理集合。要使用分片的代理集合实施多个字段的唯一性,必须为每个字段设置一个代理集合。如果在单个代理集合上创建多个唯一索引,则无法对代理集合分片。
这种方法需要为
primary_id字段创建唯一ID ,而不是让MongoDB在插入文档时自动创建。
开始之前
标识需要唯一约束但不能作为分片键一部分的字段。
确认现有文档不违反该字段的唯一性约束。
步骤
考虑一个存储用户信息的集合records。字段email 不是分片键,但必须是唯一的。 proxy集合包含以下字段:
{ "_id" : ObjectId("..."), "parent_id" : "<ID>", "email" : "<string>" }
1
2
在写入主集合之前写入代理集合。
将包含目标字段和生成的唯一ID 的文档插入到 proxy集合中。如果操作成功,则将完整文档插入 records集合:
records = db.getCollection('records'); proxy = db.getCollection('proxy'); var primary_id = ObjectId(); proxy.insertOne({ "_id" : primary_id, "email" : "example@example.net" }) // if: the above operation returns successfully, // then continue: records.insertOne({ "_id" : primary_id, "email": "example@example.net", // additional information... })