第六章 特殊的索引和集合

本章介绍MongoDB中一些特殊的集合和索引类型,包括:
  • 用于类队列数据的固定集合
  • 用于缓存的TTL索引
  • 用于简单字符串搜索的全文本索引;
  • 用于二维平面和球体空间的地理空间索引;
  • 用于存储大文件的GridFS

6.1 固定集合

MongoDB中的普通集合是动态 而且可以自动增长可以容纳更多的数据。MongoDB还有另一种不同类型的集合,叫作固定集合。说道固定大小的集合,有一个很有趣的问题,像一个已经满了的固定集合中插入数据会怎么样,答案是,固定集合的行类似于循环,如果已经没有空间了,最老的文档会被删除以释放空间。新插入的文档会 占据这块空间。也就是说,当固定空间被占满时,如果再插入新文档,固定集合会自动将最老的文档从集合中删除。

6.1.1创建固定集合

可以使用create命令创建固定集合。在shell中,可以使用createColletion函数:

db.createCollection('my_collection',{'capped':ture,'size':100000})

db.createCollection('my_collection2',{'capped':true,'size':10000,'max':100})

固定集合创建之后,就不能改变了,如果需要修改固定集合点属性,只能将它删除之后再重建,因此在创建大的固定集合之前应该仔细想清楚它的大小。

6.1.2 自然排序

对固定集合可以进行分一种特殊的排序,成为自然排序。自然排序返回结果集中文档的顺序就是文档在磁盘上的顺序。

对大多数集合来说,自然排序的意义不大,因为文档的位置经常变动。但是,固定集合中的文档是按照文档被插入的顺序保存的。自然顺序就是文档的插入顺序。因此,自然排序得到的文档就是旧到新排序的。当然也可以按照新到旧的顺序排序。

db.my_collection.find().sort({'$natural':-1})

6.1.3 循环游标

循环游标是一种特殊的游标。当循环游标的结果集被取光后。游标不会被关闭。循环游标的灵感来自tail - f命令,会尽可能久地持续提取输出结果。由于循环游标在结果集取光之后不会被关闭,因此,当有新文档插入到集合中时,循环游标会继续取到结果。由于普通集合并不维护文档的插入顺序,所有云鬟游标只能用在固定集合上。

6.1.4 有没_id索引的集合

默认情况下,每个集合都有一个_id索引,但是,如果在调用createCollection创建集合时指定autoIndexId选项为false,创建集合时就不会自动在 _id 上床架索引。实践中不建议这么使用,但是对于只有插入操作的集合来说,这确实可以带来速度上的稍许提升。

6.2 TTL索引

如果需要更加灵活的老化移出系统,。可以使用TTL索引,这种索引允许为每一个文档设计一个超时时间,一个文档到达预设置的老化程度之后就会被删除。这种类型的索引对于缓存问题非常有用。

在ensureIndex中指定恶心poreAfatterSecs选项中就可以创意一个TTL索引:

db.foo.exsureIndex({'lastUpdated':1},{'expireAfterSecs':60*24*24})

这样就在lastUpdated字段上建议了一个TTL索引,如果一个文档的lastUpdated字段存在并且他的值是日期类型,当服务器时间比文档的lastUpdated字段是时间晚expireAfterSecs秒时,文档就会把删除。

MongoDB每分钟对TTL索引进行一次清理,所以不应该依赖以秒为单位的时间保证suoy8in的存活状态。可以使用collMod命令修改expireAfterSecs的值:

db.runCommand({'collMod':'someapp.cache','expireAfterSecs':3600})

在一个给定的集合上可以有多个TTL索引。TTL索引不能是复合索引,但是可以像普通索引一样来优化排序和查询。

6.3 全文索引

MongoDB有一个忑书类型的索引用于在文档中搜索文本。前面几章都是在使用精确匹配和正则表达式来查询字符串,但是这些技术有一些限制,使用正则表达式搜索大块文本的速度非常慢,而且无法处理语言的理解问题。使用全文本索引可以非常快的进行文本搜索。就如同内置了多种语言分词机制的支持一样。

创建任何一种索引的开销都比较大。而创建全文本索引的成本更高。在一个系统频繁的集合上创建全文本索引可能会导致MongoDB过载,所以应该是离线状态下创建全文本索引,或者是在对性能没有要求时。创建全文本索引时要特别小心谨慎没存可能会不够用。

全文本索引也会导致比普通索引更严重的性能问题。因为所有字符串都需要被分解、分词,并且保存到一些地方,因此可能会发现拥有全文本索引的集合的写入性能比其他集合要差。全文本索引也会降低分片时的数据迁移速度,将数据迁移到其他分片时,所有文本都需要重新进行索引。

db.adminCommand({'setParameter':1,"textSearchEnabled":true})

6.3.1 搜索语法

默认情况下,MongoDB会使用or连接查询中的每个词, ‘ask OR hn’ 。这是执行会文本查询最有效的方式,但是也可以进行短语的精确匹配,以及使用not 为了精确查询 ‘ask hn’ 可以用 双引号将查询内容括起来:

db.runCommand({text:"hn",earqch:"\"ask hn\""})

6.3.2 优化全文索引

有几种方式可以优化全文搜索。如果能够使用某些查询条件将搜索结果的范围变小,可以创建一个由其他查询条件前缀和全文本字段组成的复合索引:

db.blog.ensureIndex({"data":1,"post":"test"})

这就是局部的全文本索引,MongoDB会基于上面例子中的date先将搜索范围分散为多个比较小的树,这样,对于特定日期的文档进行全文本查询就会快很多。

6.3.3 在其他语言中搜索

当一个文档被插入之后,MongoDB会查找索引字段,对字符串进行分词,将其减小为一个基本单元,然后不同语言的分词机制是不同的,所以必须制定索引或者文档使用的语言,文本类型的索引允许制定 default_language选项,它默认是enlish。

6.4 地理空间索引

MongoDB支持集中类型的地理空间索引,其中最常用的是2dsphere索引 和2d索引

2dsphere云心使用 GeoJSON格式指定点,线和多边形,点可以用形如[longitude,latitude] 两个元素的数组表示

6.4.1 地理空间查询的类型

可以使用多种不同类型的里空间查询:交集、包含、以及接近。查询时,需要讲希望查找地方内容指定为形如{'$geometry':genJsonDesc}的GeoJSON对象。

6.4.2 符合地理空间索引

如果有其他类型的索引,可以将地理空间索引与其他字段组合在一起使用,以便对更复杂的查询进行优化。

6.4.3 2d索引

对于非球面地图 可以使用2d索引代替 2dsphere

db.byrule.ensureIndex({'title':'2d'})

2d 索引用于扁平表面,而不是球体表面,2d索引不应该用在球体表面上,否则几点附近会出现大量的扭曲变形。

6.5 使用GridFS存储文件

GridFS是MongoDB的一种存储机制,用来存储大型二进制文件。
  • 使用GridFS能够简化你的栈。如果已经在使用MongoDB,那么可以使用GridFSB来代替独立的文件存储工具。
  • GridFS会自动平衡已有的复制或者为MongoDB设置的自动分片。所以对文件存储做故障转移或者横向扩展会更容易。
  • 当用于存储用户上传的文件时,GridFS可以比较从容地解决其他一些文件系统可能会遇到的问题。例如,在GridFS文件系统中,如果在同一个目录下存储大量的文件,没有任何问题。
  • 在GridFS中,文件存储的集中度会比较高,因为在MongoDB是以2GB为单位来分配数据文件的。
GridFS也有一些缺点:
  • GridFS的性能比较低,从MongoDB中访问文件,不如直接从文件系统中访问文件速度快。
  • 如果要修改GridFS上的文档,只能先将已有文档删除,然后在新建整个文档重新保存,MongoDB将文件作为多个文档进行存储,所以他无法再同一时间对文件中的所有快加锁。

通常来说,如果有一些不常改变戴氏经常需要联系访问的大文件,那么使用GridFS在合适不过了。

6.5.1 GridFS入门

使用GridFS最简单的方式是使用mongofiles工具,可以用它在GridFS中上传文件,下载文件,查看文件列表,搜索文件,以及删除文件。

6.5.2 在MongoDB启动程序中使用GridFS

所有客户端驱动程序提供了GridFS API。例如 pymongo 执行与上面直接使用mongofiles一样的操作:

from pymongo import Collection
import gridfs
db.Connection().test
fs = gridfs.GridFS(db)
file_id fs.put('hello',filename='foo.txt')
fs.list()
fs.get(file_id).read()

6.5.3 揭开GridFS的面纱

GridFS是一种轻量级的文件存储规范,用于存储MongoDB中的普通文档。MongoDB服务器几乎不会对GridFS请求做特殊处理,所有处理都由客户端的驱动程序和工具负责。

GridFS背后的理念是:可以将大文件分割为多个比较大的快,将每个快作为独立的文档进行存储,由于MongoDB支持在文档中存储二进制数据,所以可以将快存储的开销降到非法低。除了将文档的每一个快单独存储之外,还有一个文档用于将这些快组织在一起并存储该快的元信息。

很有书本上一些文字性的东西没有列出来不能代替全书内容。

如果对您有用,请我喝杯咖啡吧。

赞助扫码::
../../../_images/apay.jpg ../../../_images/pay_wechat.png