[权威指南]学习笔记——第4章 查询

db.c.find()相当于db.c.find({})
键值对的查询条件,数值匹配数值,布尔类型匹配布尔类型,字符串匹配字符串
指定需要返回的键,第二个参数值为1为显示,为0为不显示,默认_id总是显示
查询文档的值必须是常量,不能引用文档的其他键的值


================

$lte\$gte等的使用db.foo.findOne({"friends":{"$lte":2,"$gte":0}});
$in 查询一个键的多个值 db.foo.find({"friends":{"$in":[1,2]}});
$nin 返回与数组中所有条件都不匹配的文档
$or 可以包含其他条件db.foo.find({"$or":[{"friends":{"$in":[2]}},{"username":"aa3"}]});
$not 元条件句,可以用在任何其他条件之上,也可与正则表达式一块使用   
    db.foo.find({"friends":{"$not":{"$mod":[10,1]}}});
$and $or $nor 位于外层文档中,但是查询优化器不会对其进行优化,与其他操作符不同
    db.foo.find({"$and":[{"friends":1},{"username":"aa0"}]});


===============

null可以匹配自身,还可以匹配不包含这个键的文档,可配合$exists判断键值是否存在
     db.foo.find({"friends":{"$in":[null],"$exists":true}});
正则表达式能够灵活有效地匹配字符串。可不区分大小写的匹配哦
查询数组
db.food.find({"fruit":"apple"});查询到一个数组中有值
db.food.find({"fruit":["apple"]});


$all 如果需要通过多个元素来匹配数组,就要用$all, db.food.find({fruit:{"$all":["apple","banana"]}});
$size 查询特定长度的数组,但不能与其他查询条件(比如$gt)组合使用
$slice 可以返回某个键匹配的数组元素的一个自己,10前10个,-10后10个,[23,10]第23个开始取10个,不够10个有几个取几个,注意$slice返回文档的所有键。 db.food.find({"fruit":{"$size":3}},{fruit:{"$slice":[2,1]}});
$ 返回一个匹配的数组元素, db.foo.find({"coments.name":"tt"},{"coments.$":1})),只返回_id 和符合要求的coments

数组和范围查询的相互作用,范围会匹配任意多元素数组,可以用$elemMatch,要求两个语句与一个数组元素进行比较,$elemMatch不匹配非数组 db.foo.find({"bb":{"$elemMatch":{"$gt":1,"$lt":4}}})

查询内嵌文档与顺序相关,可以用点表示法查询, db.foo.find({"coments.name":"rr","coments.content":"beast post"})
多数需要elemMatch配合使用


====================

$where最常用的应用就是比较文档中的两个键的值是否相等,尽量少用,因为性能差
 db.foo.find({"$where":function(){
     for (var current in this){
         for (var other in this){
             if(current != other && this[current]==this[other]){
                 return true;
             }
         }
     }
     return false;
 }});

服务器端脚本  --noscripting 关闭JavaScript执行
为了避免注入攻击,应该使用作用域来传递参数的值,作用域是用于表示变量名和值的映射的wend


===================
游标
可以限制结果的数量,略过部分结果,根据任意键按任意顺序的组合对结果进行各种排序
 for(i=0;i<100;i++){
    db.collection.insert({x:i});
}
 var cursor = db.collection.find()
 while(cursor.hasNext()){
    obj = cursor.next();
    print(obj.x);
 }

cursor.forEach(function(x){
    print(x);
});

limit、skip、sort多用于分页
find后面增加limit(3),只返回3个结果,不到3个则全部返回。limit指的是上限而非下限
find后面增加skip(3),略过前3个匹配的文档,返回余下的,如果小于三个,则不返回任何文档,略过的数据越大性能越差
find后面增加sort({x:1,y:-1}),按照x升序,y降序
比较顺序
最小值<null<数字< 字符串< 对象/文档< 数组< 二进制数据 <对象id< 布尔型 <日期型 <时间戳 <正则表达式< 最大值

避免skip过大的方法有:
1、不用skip分页,可用时间倒序
2、随机选取文档,插入时为每个文档增加一个额外的随机键,Math.random()

简单查询和封装查询
$maxscan:integer,指定本次查询中扫描文档数量的上线,db.foo.find(criteria)._addSpecial("$maxscan",20)
$min:document,查询的开始条件,文档必须与索引的键完全匹配,查询中会强制使用给定的索引,强制指定一次索引扫描的下边界
$max:document,查询的结束条件,文档必须与索引的键完全匹配,查询中会强制使用给定的索引,强制指定一次索引扫描的上边界
$showDiskLoc:true,查询结果增加一个"$diskLoc"字段,用于显示该条结果在磁盘上的位置。Db.foo.find()._addSpecial('$showDiskLoc',true)

获取一致结果
数据处理通常的做法就是先把数据从MongoDB中取出来,然后做一些变换,最后再存回去,但是结果集大就会有问题,这种问题的解决办法就是对查询进行快照(snapshot),db.foo.find().snapshot(),速度会变慢,只在必要时使用。

游标生命周期
1、客户端游标,上面讲的都是
2、客户端游标表示的数据库游标
在服务器端,游标消耗内存和其他资源,游标遍历尽结果以后,或者客服端发来消息要求终止,数据库将会释放这些资源,不在作用域或者超时未使用都会销毁游标。可用immortal的函数或者类似的机制告知数据库不要让游标超时。



===================

数据库命令
drop 删除集合 db.runCommand({"drop":"test"});
 db.runCommand({getLastError:1});
 db.listCommands();查看所有的数据库命令

工作原理
返回ok,false的时候会存在errmsg表示失败原因
会子$cmd集合上执行,drop会被转换为db.$cmd.findOne({"drop":"test"});
管理员命令 adminCommand而不是runCommand。
与字段顺序相关,命令名称必须是命令中的第一个字段

posted @ 2017-07-13 11:16  石皮星  阅读(151)  评论(0)    收藏  举报