Mongodb 笔记04 特殊索引和集合、聚合、应用程序设计
特殊索引和集合
1. 固定集合:固定集合需要事先创建好看,而且它的大小是固定的。当固定集合被占满时,如果再插入新文档,固定集合会自动将最老的文档从集合中删除。
2. 创建固定集合:db.createCollection("my_collection",{"capped":true,"size":10000}) 创建一个大小为10000字节的固定集合
除了大小,createCollection还能指定固定集合中文档的数量:db.createCollection("my_collection",{"capped":true,"size":10000,"max":10})
指定文档数量时,必须同时指定集合大小。固定集合的文档数量不能超过文档数量限制,固定集合的大小也不能超过大小限制。
3. 将某个常规集合转换为固定集合:db.runCommand({"convertToCapped":"test","size":10000}) 无法将固定集合转换为非固定集合。
4. 自然排序:自然排序返回结果集中文档的顺序就是文档在磁盘上的顺序。只有固定集合中的自然排序才有意义,对其他集合来说文档位置经常变化,自然排序意义不大。
5. 循环游标:一种特殊的游标,当循环游标的结果集被取光后,游标不会被关闭。当有新文档插入到集合时,循环游标会继续取到结果。由于普通集合并不维护文档的插入顺序,循环游标只能用在固定集合上。
6. 调用createCollection创建集合时指定autoIndexId选项为false,创建集合时就不会自动在"_id"上创建索引。实践中不建议这么用,但对于只有插入操作的集合来说,这确实可以带来速度上的稍许提升。
7. TTL索引:如果需要更加灵活的老化移出系统,可以使用TTL索引,这种索引允许为每一个文档设置一个超时时间。一个文档到达预设置的老化程度之后就会被删除。这种类型的索引对于缓存问题很有用。
db.foo.ensureIndex({"lastUPdated":1},{"expireAfterSecs":60*60*24}) // 过期时间24小时
MongoDB每分钟对TTL索引进行一次清理,所以不应该依赖以秒为单位的时间保证索引的存活状态。可以使用collMod命令修改expireAfterSecs的值:
db.runCommand({"collMod":"someapp.cache","expireAfterSecs":3600})
一个给定的集合上可以有多个TTL索引,但TTL不能是复合索引。
8. 全文本索引:暂不建议使用,性能影响太大。
9. 地理空间索引:最常用的是2dsphere索引(用于地球表面类型的地图)和2d索引(用于平面地图和时间连续的数据)
10. 使用GridFS存储文件:GridFS是MongoDB的一种存储机制,用来存储大型二进制文件。
优点:
a. 简化你的栈,可以使用GRIDFS来代替独立的文件存储工具。
b. 对文件存储做故障转义或者横向扩展更容易
c. 可以比较从容地解决其他一些文件系统可能遇到的问题。
d. 文件存储的集中度会比较高
缺点:
a. 性能低:从MongoDB中访问文件,不如直接从文件系统中访问文件速度快。
b. 如果要修改GridFS上的文档,只能先将已有的文档删除。
通常来说,如果你有一些不常改变但是经常需要连续访问的大文件,那么使用GridFS再合适不过。(性能呢?因为缓存到内存了?)
11. GridFS背后的理念:可以将大文件分割为多个比较大的块,将每个快作为独立的文档进行存储。有一个文档用于将这些块组织在一起并存储该文档的元信息。
12. 可以使用任何自定义的字段来保存必须的文件元信息。可能你希望在文件元信息中保存文件的下载次数,MIME类型或者用户评分。
聚合
如果你有数据存储在MongoDB中,你想做的可能就不仅仅是将数据提取出来那么简单;你可能希望对数据进行分析加以利用。本章介绍MongoDB提供的聚合工具
1. 聚合框架:使用聚合框架可以对集合中的文档进行变化和组合。基本上,可以用多个构架创建一个管道,用于对一连串的文档进行处理。这些构件包括筛选、投射、分组、排序、限制和跳过。
2. 管道操作符:每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作(对于最后一个管道操作符,是将结果返回给客户端)。不同的
管道操作符可以按任意顺序组合在一起使用,而且可以被重复任意多次。
1). $match : $match用于对文档集合进行筛选,之后就可以在筛选得到的文档子集上做聚合。在实际使用中应该尽可能将"$match"放在管道的前面位置,这样有两个好处:
a. 可以快速将不需要的文档过滤掉,以减少管道的工作量
b. 如果在投射和分组之前执行"$match",查询可以使用索引
用法:{$match:{"state":"OR"}}
2). $project : 可以从文档中提取字段,可以重命名字段,还可以进行一些其他操作。
用法:db.articles.aggregate({"$project":{"author":1,"_id":0}}) 只返回author字段。
字段重命名:{"$project":{"userId":"$_id","_id":0}} $fieldname语法是为了在聚合框架中引用fieldname字段的值。重命名后不能使用原字段上的索引。
数学表达式:
a. $add : [expr1[,expr2....exprN] 这个操作符是接收一个或多个表达式作为参数,将这些表达式相加
b. $subtract : [expr1,expr2] 接收两个表达式,用第一个表达式减去第二个表达式作为结果
c. $multiply : [expr1[,expr2.....exprN] : 将参数相乘
d. $divide : [expr1,expr2] 第一个表达式除以第二个表达式的商作为结果
e. $mod [expr1,expr2] 第一个表达式除以第二个表达式的余数作为结果
日期表达式
$year ,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second
字符串表达式:
a. $substr : [expr,startOffset,numToReturn] : 截取字符串,从startOffset字节开始的numToReturn字节。注意是字节不是字符。
b. $concat : [expr1,expr2,....exprN] : 将给定的表达式(或者字符串)连接在一起作为返回结果
c. $toLower : expr 返回小写形式
d. $toUpper: expr 返回大写形式
逻辑运算符:
$cmp:[expr1,expr2] : 比较expr1和expr2。如果expr1等于expr2,返回0,;如果expr1小于expr2;返回负数;如果大于,返回正数
$strcasecmp:[string1,string2] : 比较字符串大小
$eq/$ne/$gt/$gte/$lt/$lte:[expr1,expr2]
几个布尔表达式:
$and:[expr1,expr2...exprN] 如果所有表达式都为true,则返回true,否则返回false
$or : [expr1,expr2...exprN] 有一个为true,则返回true
$not : expr 对表达式取反
两个控制语句:
$cond :[booleanExpr,trueExpr,falseExpr] : 如果booleanExpr为true,返回trueExpr,否则返回falseExpr
$ifNull : [expr,replacementExpr] : 如果expr为null,返回replacementExpr,否则返回expr
3). $group : $group 操作可以将文档依据特定字段的不同值进行分组。
4). $unwind : 拆分(unwind) 可以将数组的每一个值拆分成单独的文档。
5). $sort : 可以根据任何字段进行排序,与在普通查询中的语法相同。如果要对大量的文档进行排序,建议在管道的第一阶段进行排序,这样可以使用索引。
6). $limit : 接收一个数字n,返回集合中的前n个字段
7). $skip : 接收一个数字n,丢弃结果集中的前n个文档。
3. 使用管道:应该尽量在管道的开始阶段就将尽可能多的文档和字段过滤掉。管道如果不是直接从原先的集合中使用数据,那就无法再筛选和排序中使用索引。如果可能,聚合管道会尝试对操作进行排序,
以便能够有效的使用索引。如果MongoDB发现某个聚合操作占用了20%以上的内存,这个操作就会直接输出错误。
如果能够通过$match操作迅速减小结果集的大小,就可以使用管道进行实时聚合。
4. MapReduce : 非常强大,非常灵活。但速度慢,不应该用在实时的数据分析中。
5. 聚合命令:
1). count : db.foo.count()
2). distinct : db.runCommand({"distinct":"people","key":"age"})
3). group
应用程序设计
1. 范式化:将数据分散到多个不同的集合,不用集合之间可以相互引用数据。虽然很多文档可以引用某一块数据,但是这块数据只存储在一个集合。
反范式化:将每个文档所需的数据都嵌入在文档内部。每个文档都拥有自己的数据副本,而不是所有文档共同引用同一个数据副本。
范式化能够提高数据写入速度,反范式化能够提高数据读取速度。
2. 更适合内嵌:子文档较小,数据不会定期改变,最终数据一致性即可,文档数据小幅增加,数据通常需要执行二次查询才能获得,快速读取
更适合引用:子文档较大,数据经常变化,中间阶段的数据必须一致,文档数据大幅增加,数据通常不包含在结果中,快速写入
3. 优化数据操作:如果要优化应用程序,首先必须知道对读写性能进行评估以便能找到性能瓶颈。对读取操作的优化通常包括正确使用索引,以及尽可能将所需信息放在单个文档中返回,
对写入操作的优化通常包括减少索引数量以及尽可能提高更新效率。
4. 经常需要再写入效率更高的模式与读取效率更高的模式之间权衡,所以必须要知道哪种操作对你的应用程序更重要。这里的影响因素并不只是读取和写入的重要性,也包括读取和写入操作的频繁程度.
5. 数据优化方式:
1). 优化文档增长:更新数据时,需要明确更新是否会导致文件体积增大,以及增长程度。如果增长程序是可预知的,可以为文档预留足够的增长空间,这样可以避免文档移动,提高写入速度。
检测一下填充因子,如果它大约是1.2或者更大,可以考虑手动填充。如果要对文档手动填充,可以在填充文档时创建一个占用空间比较大的字段,文档创建成功之后删除这个字段。
插入时添加或者在upsert时,使用$setOnInsert创建这个字段。更新文档时,使用$unset移除。如果这个字段不存在,$unset操作什么也不做。
可以考虑将会增长的字段,放在最后面。
2). 删除旧数据,主要有三种方式:使用固定集合,使用TTL集合,使用定期删除集合。
6. 一致性管理:
服务器为每个数据库连接维护一个请求队列。客户端每次发来的新请求都会添加到队列末尾。入队之后,这个连接上的请求会一次得到处理。一个连接拥有一个一致的数据库视图,可以总是读取到这个
连接最新写入的数据。注意,每个队列只对应一个连接:如果打开两个shell,连接到相同的数据库,这时就存在两个不同的连接。如果在齐中一个shell中执行插入操作,紧接着在另一个shell中执行
查询操作,新插入的数据肯呢个不会出现在查询结果中。
7. 不适合使用MongoDB的场景:
1). MongoDB不支持事务
2). 无法在多个维度上对不同类型的数据库进行连接。
3). 你使用的工具不支持MongoDB
Mongodb 笔记04 特殊索引和集合、聚合、应用程序设计的更多相关文章
- 6.MongoDB系列之特殊索引和集合类型
1. 地理空间索引及全文搜索 与Elasitcsearch一样,MongoDB同样支持地理空间索引及全文搜索,由于选型常用ES而非MongoDB此处略过 2. TTL索引 首先先了解下固定集合,其类似 ...
- JS自学笔记04
JS自学笔记04 arguments[索引] 实参的值 1.对象 1)创建对象 ①调用系统的构造函数创建对象 var obj=new Object(); //添加属性.对象.名字=值; obj.nam ...
- MongoDB学习笔记-04 索引
索引是用来加速查询的.有了索引之后,数据库不必进行全表扫描,只需先在索引中查找,再根据找到的索引查找数据.MongoDB的索引几乎和传统关系型数据库一样. 创建索引 创建索引是在相应的集合中使用ens ...
- Mongodb Manual阅读笔记:CH7 索引
7索引 Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mongodb Manual阅读笔记 ...
- MongoDB学习笔记四:索引
索引就是用来加速查询的.创建数据库索引就像确定如何组织书的索引一样.但是你的优势是知道今后做何种查询,以及哪些内容需要快速查找.比如:所有的查询都包括"date"键,那么很可能(至 ...
- MongoDB学习笔记04
创建索引使用ensureIndex方法,对于同一个集合,同样的索引只需要创建一次,反复创建是徒劳的. 对某个键的索引会加速对该键的查询,然而,对于其它查询可能没有帮助,即便是查询中包含了被索引的键.实 ...
- Mongodb 笔记03 查询、索引
查询 1. MongoDB使用find来进行查询.find的第一个参数决定了要返回哪些文档,这个参数是一个文档,用于指定查询条件.空的查询会匹配集合的全部内容.要是不指定查询,默认是{}. 2. 可以 ...
- MongoDB 学习笔记之 TTL索引,部分索引和文本索引
TTL索引: TTL集合支持mongodb对存储的数据进行失效时间设置,经过指定的时间段后.或在指定的时间点过期,集合自动被mongod清除.这一特性有利于对一些只需要保存一定时间的数据信息进行存储, ...
- mongodb笔记(三)
1.删除文档(remove()函数) 在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯. 语法: db.collection.remove( <q ...
随机推荐
- 对Largest函数的测试
题目:查找list[]中的最大值:int Largest(int list[], int length); int Largest(int list[], int length) { int i,ma ...
- Java第二天——标识符命名规则、Java的知识、快捷键的使用、Scanner获取值的常用方法
1.标识符命名规则 字母.下划线.数字.美元符号($)由这四个部分组成. 标识符=首字母+其他 首字母:字母.下划线.美元符号($) 其他:字母.下划线.数字.美元符号($) 注意: 1.首字母不能为 ...
- 《TCP/IP 详解 卷1:协议》第 4 章:地址解析协议
链路层是经过单一链路通信的协议层. IP 网络层协议的设计目标是为跨越不同物理类型的.多节点网络的 packet ,提供主机寻址.路由操作. 在其中要注意的一点是:网络层使用的地址和底层网络硬件使用的 ...
- python字符串操作、文件操作,英文词频统计预处理
1.字符串操作: 解析身份证号:生日.性别.出生地等. 凯撒密码编码与解码 网址观察与批量生成 解析身份证号:生日.性别.出生地等 def function3(): print('请输入身份证号') ...
- 带复杂类的list,list<class>前台往后台传输
1.前台 $("#applyGoods").click(function(){ var usid=$(this).next().text(); var aid=$(this).ne ...
- HDU 2086 A1 = ?
http://acm.hdu.edu.cn/showproblem.php?pid=2086 Problem Description 有如下方程:Ai = (Ai-1 + Ai+1)/2 - Ci ( ...
- VMWare之——宿主机与虚拟机互相ping通,宿主机ping通另一台机器的虚拟机
版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处:http://blog.csdn.NET/l1028386804/article/details/52267554 今天给大家带来 ...
- php SPL标准库iterator和ArrayAccess的学习
最近在补充学习php基础的时候看到了spl的介绍,学习了一下iterator和arrayAccess的使用,iterator主要是对象的迭代,一般可以用在容器里面,或者工厂模式里面,最常见的应用场景就 ...
- vSphere下安装Hyper-V
在vSphere 5.5中默认是无法嵌套安装Hyper-V的,必须在vSphere中稍作修改. 1. 勾选这两个选项,如果是灰色,请升级虚拟机版本至最新: 2. 在配置文件中手动加入这一行参数: 3. ...
- 原生Ajax函数
前言 在日常工作中,我经常使用Jquery的Ajax来获取接口数据.这几天有一个的官网要制作,由于网站比较小,有一些与服务器通信的接口处理,并没有涉及到复杂的交互功能.为了可以减少加载Jquery库的 ...