MongoDB指南---13、索引类型

栏目: 数据库 · 发布时间: 5年前

内容简介:上一篇文章:下一篇文章:创建索引时可以指定一些选项,使用不同选项建立的索引会有不同的行为。接下来的小节会介绍常见的索引变种,更高级的索引类型和特殊选项会在下一章介绍。

上一篇文章: MongoDB指南---12、使用explain()和hint()、何时不应该使用索引

下一篇文章:

创建索引时可以指定一些选项,使用不同选项建立的索引会有不同的行为。接下来的小节会介绍常见的索引变种,更高级的索引类型和特殊选项会在下一章介绍。

唯一索引

唯一索引可以确保集合的每一个文档的指定键都有唯一值。例如,如果想保证同不文档的"username"键拥有不同的值,创建一个唯一索引就好了:

> db.users.ensureIndex({"username" : 1}, {"unique" : true})

如果试图向上面的集合中插入如下文档:

> db.users.insert({username: "bob"})
> db.users.insert({username: "bob"})
E11000 duplicate key error index: test.users.$username_1 dup key: { : "bob" }

如果检查这个集合,会发现只有第一个"bob"被保存进来了。发现有重复的键时抛出异常会影响效率,所以可以使用唯一索引来应对偶尔可能会出现的键重复问题,而不是在运行时对重复的键进行过滤。

有一个唯一索引可能你已经比较熟悉了,就是"_id"索引,这个索引会在创建集合时自动创建。这就是一个正常的唯一索引(但它不能被删除,而其他唯一索引是可以删除的)。

如果一个文档没有对应的键,索引会将其作为null存储。所以,如果对某个键建立了唯一索引,但插入了多个缺少该索引键的文档,由于集合已经存在一个该索引键的值为null的文档而导致插入失败。5.4.2节会详细介绍相关内容。

有些情况下,一个值可能无法被索引。索引储桶(index bucket)的大小是有限制的,如果某个索引条目超出了它的限制,那么这个条目就不会包含在索引里。这样会造成一些困惑,因为使用这个索引进行查询时会有一个文档凭空消失不见了。所有的字段都必须小于1024字节,才能包含到索引里。如果一个文档的字段由于太大不能包含在索引里,MongoDB不会返回任何错误或者警告。也就是说,超出8 KB大小的键不会受到唯一索引的约束:可以插入多个同样的8 KB长的字符串。

1. 复合唯一索引

也可以创建复合的唯一索引。创建复合唯一索引时,单个键的值可以相同,但所有键的组合值必须是唯一的。

例如,如果有一个{"username" : 1, "age" : 1}上的唯一索引,下面的插入是合法的:

db.users.insert({"username" : "bob"})

db.users.insert({"username" : "bob", "age" : 23})

db.users.insert({"username" : "fred", "age" : 23})

然而,如果试图再次插入这三个文档中的任意一个,都会导致键重复异常。

GirdFS是 MongoDB 中存储大文件的标准方式(详见6.5节),其中就用到了复合唯一索引。存储文件内容的集合有一个{"files_id" : 1, "n" : 1}上的复合唯一索引,因此文档的某一部分看起来可能会是下面这个样子:

{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 1}

{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 2}

{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 3}

{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 4}

注意,所有"files_id"的值都相同,但是"n"的值不同。

2. 去除重复

在已有的集合上创建唯一索引时可能会失败,因为集合中可能已经存在重复值了:

> db.users.ensureIndex({"age" : 1}, {"unique" : true})
E11000 duplicate key error index: test.users.$age_1 dup key: { : 12 }

通常需要先对已有的数据进行处理(可以使用聚合框架),找出重复的数据,想办法处理。

在极少数情况下,可能希望直接删除重复的值。创建索引时使用"dropDups"选项,如果遇到重复的值,第一个会被保留,之后的重复文档都会被删除。

> db.people.ensureIndex({"username" : 1}, {"unique" : true, "dropDups" : true})

"dropDups"会强制性建立唯一索引,但是这个方式太粗暴了:你无法控制哪些文档被保留哪些文档被删除(如果有文档被删除的话,MongoDB也不会给出提示说哪些文档被删除了)。对于比较重要的数据,千万不要使用"dropDups"。

稀疏索引

前面的小节已经讲过,唯一索引会把null看做值,所以无法将多个缺少唯一索引中的键的文档插入到集合中。然而,在有些情况下,你可能希望唯一索引只对包含相应键的文档生效。如果有一个可能存在也可能不存在的字段,但是当它存在时,它必须是唯一的,这时就可以将unique和sparse选项组合在一起使用。

MongoDB中的稀疏索引(sparse index)与关系型数据库中的稀疏索引是完全不同的概念。基本上来说,MongoDB中的稀疏索引只是不需要将每个文档都作为索引条目。

使用sparse选项就可以创建稀疏索引。例如,如果有一个可选的email地址字段,但是,如果提供了这个字段,那么它的值必须是唯一的:

> db.ensureIndex({"email" : 1}, {"unique" : true, "sparse" : true})

稀疏索引不必是唯一的。只要去掉unique选项,就可以创建一个非唯一的稀疏索引。

根据是否使用稀疏索引,同一个查询的返回结果可能会不同。假如有这样一个集合,其中的大部分文档都有一个"x"字段,但是有些没有:

> db.foo.find()
{ "_id" : 0 }
{ "_id" : 1, "x" : 1 }
{ "_id" : 2, "x" : 2 }
{ "_id" : 3, "x" : 3 }

当在"x"上执行查询时,它会返回相匹配的文档:

> db.foo.find({"x" : {"$ne" : 2}})
{ "_id" : 0 }
{ "_id" : 1, "x" : 1 }
{ "_id" : 3, "x" : 3 }

如果在"x"上创建一个稀疏索引,"_id"为0的文档就不会包含在索引中。如果再次在"x"上查询,MongoDB就会使用这个稀疏索引,{"_id" : 0}的这个文档就不会被返回了:

> db.foo.find({"x" : {"$ne" : 2}})
{ "_id" : 1, "x" : 1 }
{ "_id" : 3, "x" : 3 }

如果需要得到那些不包含"x"字段的文档,可以使用hint()强制进行全表扫描。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言程序设计

C语言程序设计

K. N. King / 吕秀锋、黄倩 / 人民邮电出版社 / 2010-4 / 79.00元

时至今日, C语言仍然是计算机领域的通用语言之一,但今天的 C语言已经和最初的时候大不相同了。本书最主要的一个目的就是通过一种“现代方法”来介绍 C语言,书中强调标准 C,强调软件工程,不再强调“手工优化”。这一版中紧密结合了 C99标准,并与 C89标准进行对照,补充了 C99中的最新特性。本书分为 C语言的基础特性、 C语言的高级特性、 C语言标准库和参考资料 4个部分。每章末尾都有一个“问与......一起来看看 《C语言程序设计》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具