6.1固定集合
MongoDB中的"普通"集合是动态创建的,而且可以自动增长以容纳更多的数据。MongoDB中还有另一种不同类型的集合,叫做固定集合,固定集合需要事先创建好,而且它的大小是固定的。
固定集合的访问模式与MongoDB中的大部分集合不同:数据被顺序写入磁盘上的固定空间。因此它们在蝶式磁盘(spinning disk)上的写入速度非常快,尤其是集合拥有专用磁盘时(这样就不会因为其他集合的一些随机性的写操作而"中断")。
6.1.1 创建固定集合
> db.createCollection("my_collection",{"capped":true,"size":100000});
{ "ok" : 1 }
> db.createCollection("my_collection2",
... {"capped":true,"size":100000,"max":100});
{ "ok" : 1 }
例如将test集合转换为一个大小为10000字节的固定集合:
> db.runCommand({"convertToCapped":"test","size":10000});
无法将固定集合转换为非固定集合(只能将其删除)
6.1.2 自然排序
对固定集合可以进行一种特殊的排序,称为自然排序(natural sort)。固定集合中的文档是按照文档被插入的顺序保存的,自然顺序就是文档的插入顺序。
6.1.3 循环游标
循环游标(tailable cursor)是一种特殊的游标,当循环游标的结果集被取光后,游标不会被关闭。由于循环游标在结果集取光之后不会被关闭,因此,当有新文档插入到集合中时,循环游标会继续取到结果。由于普通集合并不维护文档的插入顺序,所以循环游标只能用在固定集合上。如果10分钟没有新的结果,循环游标就会被释放,因此,当游标被关闭时自动重新执行查询是非常重要的。
6.1.4 没有_id索引的集合
如果在调用createCollection创建集合时指定autoIndexId选项为false,创建集合时就不会自动在"_id"上创建索引。"_id"索引必须是唯一索引。"_id"索引必须一次成功!如果创建的"_id"索引不和规范,就只能删除集合再重建了。
6.2 TTL索引
TTL索引(time-to-live index,具有生命周期的索引),这种索引允许为每一个文档设置一个超时时间。一个文档到达预设置的老化程度之后就会被删除。
在ensureIndex中指定expireAfterSecs选项就可以创建一个TTL索引:
当服务器时间比文档的"lastUpdated"字段的时间晚expireAfterSecs秒时,文档就会被删除。
MongoDB每分钟对TTL索引进行清理。
6.3 全文本索引
MongoDB有一个特殊类型的索引用于在文档中搜索文本。使用正则表达式搜索大块文本的速度非常慢,而且无法处理语言的理解问题。使用全文本索引可以非常快的进行文本搜索,就如同内置了多种语言分词机制的支持一样。创建任何一种索引的开销都比较大,而创建全文本索引的成本更高。全文本索引也会导致比"普通"索引更为严重的性能问题,因为所有字符串都需要被分解、分词,并且保存到一些地方。
启动MongoDB时指定--setParameter textSearchEnabled=true选项,或者在运行时执行setParameter命令,都可以启用全文本索引:
> db.amdinCommand({"setParameter":1,"textSearchEnabled":true})
为了进行文本搜索,首先需要创建一个"text"索引:
> db.hn.ensureIndex({"title":"text"})
现在,必须通过text命令才能使用这个索引:
匹配到的文档是按照相关性降序排列的:"Ask HN"位于第一位,然后是两个部分匹配的文档。每个对象前面的"score"字段描述了每个结果与查询的匹配程度。
全文本索引只会对字符串数据进行索引:其他的数据类型会被忽略,不会包含在索引中。一个集合上最多只能有一个全文本索引,但是全文本索引可以包含多个字段:
> db.blobs.ensureIndex({"title":"text","desc":"text","author":"text"})
全文本索引的字段顺序不重要:每个字段都被同等对待。可以为每个字段指定不同的权重来控制不同字段的相对重要性:
> db.hn.ensureIndex({"title":"text","desc":"text","author":"text"}, {"weights":{"title":3,"author":2}})
默认的权重是1,权重的范围可以是1-1000000000.
索引一经创建,就不能改变字段的权重了。
可以使用"$**"在文档的所有字符串字段上创建全文本索引:这不仅会对顶级的字符串字段建立索引,也会搜索嵌套文档和数组中的字符串字段:
> db.blobs.ensureIndex({"$**":"text"})
也可以为"$**"设置权重:
> db.hn.ensureIndex({"whatever":"text"},
... {"weights":{"title":3,"author":1,"$**":2}})
6.3.1 搜索语法
为了精确查询"ask hn"这个短语,可以用双引号将查询内容括起来:
这比使用OR的匹配慢一些,因为MongoDB首先要执行一个OR匹配,然后在对结果进行AND匹配。
可以将查询字符串的一部分指定为字面量匹配,另一部分仍然是普通匹配:
> db.runCommand({text:"hn",search:"\"ask hn\" ipod"})
这会精确搜索"ask hn"这个短语,也会可选地搜索"ipod"。
也可以使用"-"字符指定特定的词不要出现在搜索结果中:
>db.runCommand({text:"hn",search:"-startup vc"})
这样就会返回匹配"vc"但是不包含"startup"这个词的文档。