MonogoDB官网上提供了许多免费课程,就选择了"MongoDB for node.js developers"学习。课程当然是英文的啦,不过有中文字幕~,每次课程后还有练习。七周的课程过去的很快,学到了不少的内容。借助着最终测试的题,做一次小结,省得自己不久后忘记(哎,记性差= =)
最后的测试一共有十道题,考察的内容分别是:1、查询 2、聚合 3、更新$addToSet 4、更新$inc 5、索引 6、添加优化 7、游标 8、副本 9、片键 10、索引的explain属性
1、查询
function ( query , fields , limit , skip, batchSize, options ){ var cursor = new DBQuery( this._mongo , this._db , this , this._fullName , this._massageObject( query ) , fields , limit , skip , batchSize , options || this.getQueryOptions() ); var connObj = this.getMongo(); var readPrefMode = connObj.getReadPrefMode(); if (readPrefMode != null) { cursor.readPref(readPrefMode, connObj.getReadPrefTagSet()); } return cursor; }
从上面的函数可以看出find函数接受6个参数,query查询条件,fields指定需要返回的键,limit限制返回结果,skip跳过X个查询结果,batchSize设置返回批次数量,option其他设置。
查询条件可以查询大于($gt),小于($lt),或查询等等。详细用法见官网。
Mongo还可以对数组进行查询,用法不难,像查询一个数组里有没有包含一个要查找内容,这时跟普通的查询没有任何区别,这时查找到的内容是数组的子集。如果只要完全符合自己的查询条件的结果,要使用$all。如果要查询的结果包含任意查询条件时,使用$in。
很多时候我们知道我们要找的内容在数组的位置时,可以使用像下标的方式查找。像
db.inventory.find( { 'memos.0.by': 'shipping' } )
0表示位于数组的第一位置,后面的".by"是指查询其内嵌文档,这是mongo提供的dot语法。
2、聚合
聚合可以使我们分析数据,它使用了管道的概念,也就是通过一组数组设置一系列顺序执行的任务,每个任务的结果是下一个任务的输入。
借用官网的一张图:
上面的聚合中先匹配了status等于A的文档,然后根据cust_id分组并对各分组的amount加总。
总共提供了筛选管道操作符$match,$limit,$skip,排序管道操作符$sort,分组操作符$group,投射操作符$project和拆分操作符$unwind等。
3、更新 $addToSet
直接使用update是整体覆盖型更新,而我们常常只要更新文档的一部分。一般常用$set修改器,当我们想对一个数组添加内容时可以使用$push,但$push只是单纯添加到数组末尾,如果我们要保证数组内的内容唯一性的话应该使用$addToSet
//syntax { $addToSet: { <field1>: <value1>, ... } }; //example db.test.update( { _id: 1 }, { $addToSet: {letters: [ "c", "d" ] } } )
4、更新$inc
$inc修改器用来增加已有的键值,或者不存在就创建一个。
在这道题上自己遇到了点问题。我需要对一个数组内给定的位置的文档更新,位置是一个变量,这里假设是变量名是comment_ordinal
你可以像上面提到的Array.0.foo来更新
{$inc: {Array.0.foo: 1}}
但不可以像以下的方法来更新
{$inc: {Array.comment_ordinal.foo: 1}; //直接报错 {$inc: {"Array.comment_ordinal.foo": 1}; //会创建一个Array:[{comment_ordinal.foo: 1},.....]
那时候自己就卡在这里。。。。。现在想想也是思维被框框架架给限制住了。
{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
看惯了这样的写法后就忘了{ <field1>: <amount1>, <field2>: <amount2>, ... }这东西也是个对象啊!!!
var selector = {}; selector['comments.' + comment_ordinal + '.num_likes'] = 1; posts.update({'permalink': permalink}, {$inc: selector},.......)
可以把{Array.0.foo: 1}整个包裹起来嘛~,这样就ok了。
5、索引
索引能提供更高效的查找,当然有些时候相反。
索引基本有3种类型:单键索引、复合索引、多键索引
单键索引:db.friends.createIndex( { "name" : 1 } )
复合索引:db.products.createIndex( { "item": 1, "stock": 1 } )
多键索引:如果索引的某个键在某个文档中是一个数组,那么这就会被mongodb自动为多键索引,不需要你额外的设置。这在查询数组时会很有效率(官网上这么写着,没实践过)