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()强制进行全表扫描。


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

查看所有标签

猜你喜欢:

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

OKR工作法

OKR工作法

克里斯蒂娜•沃特克 (Christina Wodtke) / 明道团队 / 中信出版社 / 2017-9-1 / CNY 42.00

《OKR工作法》讲述了一种风靡硅谷科技企业的全新工作模式。 如何激励不同的团队一起工作,全力以赴去实现一个有挑战性的目标? 硅谷的两个年轻人汉娜和杰克,像很多人一样,在萌生了一个创意后,就走上创业之路。但是,很快他们发现好的想法远远不够,必须还有一套适合的管理方法确保梦想能实现。为了让创业团队生存下来,汉娜和杰克遭受了内心的苦苦挣扎和煎熬。他们患上“新奇事物综合症”,什么都想做,导致无......一起来看看 《OKR工作法》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具