
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
4.5 唯一性约束
在现实场景中,唯一性是很常见的一种索引约束需求,重复的数据记录会带来许多处理上的麻烦,比如订单的编号、用户的登录名等。通过建立唯一性索引,可以保证集合中文档的指定字段拥有唯一值。
在创建索引时,通过指定unique=true选项可以将其声明为唯一性索引,代码如下:

此后,如果尝试写入两个拥有相同标题的book文档,则将会得到如下错误提示:

对于指定字段已经存在重复记录的集合,如果尝试创建唯一性约束的索引,则会提示如下错误:

1.复合索引的唯一性
除了单字段索引,还可以为复合索引使用唯一性约束。如果只是希望分类下的书籍标题保持唯一性,那么可以建立复合式的唯一性索引,代码如下:

2.嵌套文档的唯一性
唯一性约束同样可以用于嵌套文档的某个字段,这和普通索引没有什么区别,比如:

但如果希望将整个嵌套文档作为唯一性的保证,那么在使用时可能会造成困扰,比如:

嵌套文档的唯一性约束是严格按照写入顺序进行比较的,如下代码所示,尽管写入的文档内容是一样的,但由于字段的顺序不一致,MongoDB仍然认为这是不同的文档。为了避免产生困扰,建议尽量少用这种做法。

3.数组的唯一性
如果对数组索引(multikey index)使用唯一性约束,那么可以保证所有的文档之间不会存在重叠的数组元素,代码如下:

但是,数组索引上的唯一性约束并无法保证同一个文档中包含重复的元素,如下面的语句是可以写入成功的:

注意,如果数组中的元素是嵌套的文档,那么同样会遇到字段次序的问题。
4.使用约束
● 唯一性索引对于文档中缺失的字段,会使用null值代替,因此不允许存在多个文档缺失索引字段的情况。
● 对于分片的集合,唯一性约束必须匹配分片规则。换句话说,为了保证全局的唯一性,分片键必须作为唯一性索引的前缀字段。