固定集合
需要事先创建好,而且它的大小是固定的。当固定集合没有空间时,再插入新的文档,最老的文档会被删除。固定集合的访问方式:数据被写入磁盘上的固定空间,它们在蝶式磁盘上的写入速度非常快,尤其是拥有专用磁盘时。
创建
固定集合必须在使用之前显示创建。
> 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权威指南