固定集合

需要事先创建好,而且它的大小是固定的。当固定集合没有空间时,再插入新的文档,最老的文档会被删除。固定集合的访问方式:数据被写入磁盘上的固定空间,它们在蝶式磁盘上的写入速度非常快,尤其是拥有专用磁盘时。

创建

固定集合必须在使用之前显示创建。

  1. > db.createCollection({"my_collection":{"capped":true,"size":100000});

除了指定大小,还可以指定固定集合中文档的数量

> db.createCollection({"my_collection":{"capped":true,"size":100000,"max":100});

将一个已有集合转为固定集合

> db.runCommand({ "convertToCapped" : "test", "size" : 10000 });

自然排序

返回结果集中文档的顺序就是文档在磁盘上的顺序,默认是由旧到新的顺序。

按照由新到旧的顺序排列

> db.my_coolection.find().sort({"$$natural":-1});

循环游标

当循环游标的结构集被取光后,游标不会关闭。它只能用于固定集合上。循环游标通常被用于当文档被插入到“工作队列”时对新插入的文档进行处理。如果超过 10 分钟没有新的结果,循环游标就会被释放,因此,循环游标被关闭时重新执行查询时非常重要的。(不能在 MongoDB shell 中 使用循环游标)

没有 _id 索引的集合

事件中不建议这么使用,但是对于只有插入操作的集合来说, 确实可以提高速度。一个没有 _id 的集合不能复制它所在的 mongod 。

TTL 索引

允许为每个文档设置一个超时时间。一个文档达到预设的老化程度之后会被删除。这种索引对于缓存问题(比如会话的保存)非常有用。

创建一个 TTL 索引

> db.foo.ensureIndex({"lastUpdated" : 1}, {"expireAferSecs" : 60*60*24 });

如果 lastUpdated 字段是个日期类型,当服务器日期比它晚 expireAfterSecs 秒时,文档会被删除。

全文本索引

创建全文本索引的成本很高,可能导致内存不够用。

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

> db.hn.ensureIndex({"title" : "text"});

这个搜索是不区分大小写的。全文索引只会对字符串数据进行索引,其他的数据类型被忽略,不包含在索引中。一个集合上最多只能有一个全文索引,但是全文索引可以包含多个字段:

> db.hn.ensureIndex({"title" : "text","desc" : "text","author" : "text"});

搜索语法

> db.runCooand({text : "hn",search : "\"ask hn\""});

优化全文本索引

使用条件查询将搜索结果的范围变小,创建一个其他查询前缀和全文本字段组成的复合索引

> db.blog.ensureIndex({"date" : 1,"post" : "text"});

也可以使用其他查询条件后缀,使索引能够覆盖查询。

> db.blog.ensureIndex({"post" : "text","author" : 1});

前缀和后缀形式可以组合使用

> db.blog.ensureIndex({"date" : 1,"post" : "text","author" : 1});

地理空间索引

2dsphere 索引(用于地球表面类型的地图)

{
    "name":"New York City",
    "loc" : {
        "type":"Point",
        "coordinates":[50,2]
    }
}

地理空间查询的类型

交集、包含以及接近。

找出与查询位置相交的文档:

> var eastVillage = {
    "type":"Polygon",
    "coordinates":[
        [-73.9917900, 40.7264100],
        [-73.9917900, 40.7324100],
        [-73.9829300, 40.7324100],
        [-73.9829300, 40.7264100],
    ]
};

> db.open.street.map.find({"loc":{"$geoIntersects":{"$geometry":eastVillage}})

查询完全包含在某地区的文档

> db.open.street.map.find({"loc":{"$within":{"$geometry":eastVillage}})

查询附近的位置,返回结果距离由近到远

> db.open.street.map.find({"loc":{"$near":{"$geometry":eastVillage}})

2d 索引

对于非球面地图(游戏地图、时间连续的数据等)

> db.hyrule.ensureIndex({"title":"2d"})

2d 索引只能对点进行索引。可以保存由点组成的数组,但它们不会被连成线。

设置索引边界值

> db.hyrule.ensureIndex({"light-years":"2d"},{"min":-1000,"max":1000})

查询某个形状范围内的所有文档

> db.hyrule.find({ "title" : {"$within" : {"$box" : [[10,20], [15,30]] }}})

$box 接收一个两元素的数组:第一个元素指定左下角的坐标,第二个元素指定右上角的坐标。

使用 GridFS 存储文件

用来存储大型二进制文件

优点

  • 简化你的栈。

  • 自动平衡已有的复制或者为MongoDB设置的自动分片,对文件存储做故障转移或者横向拓展会很容易。

  • 当用于存储用户上传文件时,比较从容的解决一些文件可能会遇到的问题。

  • 文件存储的集中度高

缺点

  • 性能比较低。不如文件系统里访问快。

  • 要修改文档,只能将已有文档删除,再整个文档重新保存。

  • 将文件作为多个文档进行存储,它无法在同一时间对文件中的所有块加锁。

如果你有一些不常改变但需要连续访问的文件,使用它最合适不过。

GridFS 的神秘面纱

它是一种轻量级的文件存储规范,用于存储 MongoDB 中的普通文档。将大文件分割成几个比较大的块,将每个块作为独立的文档进行存储。

块具有的几个键:

  • files_id

块所属的文件的元信息

  • n

块在文件中的相对位置

  • data

块所包含的二进制数据

GridFS 必须的几个键:

  • id

文件的唯一 id,这个键是每个块文件中的 files_id 的值。

  • length

文件所包含的字节数。

  • chunkSize

组成文件的每个块的大小,单位字节。默认是 256 KB ,可以调整。

  • uploadDate

文件被上传到 GridFS 的日期。

  • md5

文件内容的 md5 效验值,这个值由服务器端计算得到。

参考

[1] MongoDB权威指南