学云签约讲师王泽Mongodb开发视频教程—第八讲Mongodb查询操作(下)学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台上节回顾•find和findOne函数介绍•查询条件使用方法•特定类型的查询学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台本节目标•$where子句的使用•游标的使用方法$where子句的使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•$where,可以执行任意JavaScript作为查询的一部分!最典型的应用:一个文档,如果有两个键的值相等,就选出来,否则不选。•使用$where其实就是写了一个javascript函数,MongoDB在查询时,会将每个文档转换成一个javascript对象,然后扔到这个函数中去执行,通过返回结果来判断其是否匹配!在实际使用中,尽量避免使用”$where条件操作符,因为其性能很差!在执行过程中,需要把每个档案转化为javascript对象!$where子句的使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•如果不可避免,则尽量这样写:find({”other“:”......“,......,“$where”:}),即将$where放最后,作为结果调优,让常规查询作为前置过滤条件!这样能减少一些性能损失!•{_id:id,age:25,books:[js,c++],c:90,country:AUS,school:[{school:k,score:A},{school:k1,score:A1}],size:5}•查询年龄大于22,喜欢看c++,在k学校上学的学生$where子句的使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•比较document里边两个key的值。举个例子,我们有个list,我们想返回里边的key的值里有相等的document。•db.foo.insert({apple:1,banana:6,peach:3})•db.foo.insert({apple:8,spinach:4,watermelon:4})•第二个document里,菠菜和西瓜的值是相等的,这个应该返回,这个使用$条件查询符号是做不到的。游标的使用方法学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•MongoDB中find()函数返回一个游标,客户端通过对游标进行一些设置就能对查询结果进行有效地控制,如可以限制查询得到的结果数量、跳过部分结果、或对结果集按任意键进行排序等!我们之前在Shell中进行操作,都是直接使用find()函数,并没有使用其返回值,游标的使用方法学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•我们先通过javascript脚本向集合中填充100条文档,然后直接调用find函数。其会自动递归find返回的游标,将前20条数据展示在shell中。如果我们通过变量保留find函数的返回值,其不会自动进行遍历显示操作。•varcursor=db.coll.find();游标的使用方法学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•调用完find后,此时Shell并不会去真正地访问数据库,而是等待开始要求获得结果的时候才向数据库发送查询请求!我们此时可以对这个游标进行各种设置,然后调用游标的hashNext()或next()方法,这样就会真正访问数据库,这是一个懒加载的过程。如下•varcursor=db.coll.find();•while(cursor.hasNext()){•...vardoc=cursor.next();•...//dostuffwithdoc•...};游标的使用方法学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•cursor.hasNext()cursor.next();•上述代码中,当调用cursor.hasNext()时,查询被发往数据库,默认会返回前100条文档或者前4M的数据(两者之中较小的),这样下次next或hasNext都是本地调用了!当这组数据被遍历完毕,hasNext会导致再次去访问数据库,直到所有结果被返回limit、skip、sort使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•有3个函数limit、skip、sort可以在处理游标时使用。limit是限制游标返回的数量,指定了上限;skip是忽略前面的部分文档,如果文档总数量小于忽略的数量,则返回空集合;sort对得到的子集合进行排序,可以按照多个键进行正反排序!对游标的操作有一个技巧就是,操作游标的函数返回的都是游标,所以可以组成方法链调用。limit、skip、sort使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•1、db.fruitprice.find();•2、db.fruitprice.find().sort({apple:1,banana:-1});•3、db.fruitprice.find().skip(1).limit(3).sort({apple:1,banana:-1});•第一次只执行了find函数,返回了一个集合,没有顺序。•第二次按照键apple键banana排序,键apple升序(0的数字),键“banana”降序(0的数字),即先按找键“apple”升序排,对于键“apple”相等的文档,则按照键“banana”降序limit、skip、sort使用学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•第三次使用了三个函数来设置游标。这三个函数的关系是,在数据库服务器端,先执行sort,然后再排好序的文档上执行skip,最后按照limit设定的最大数量返回文档子集即可。相同键的比较顺序学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•按照键排序时,MongoDB中对于键并不会强制其值是什么类型,我们在实际中也会遇到同一个键,一个文档中为串在另一个文档中为数字,这种文档在排序时是任何进行的呢?MongoDB中,有一个预先定义的顺序,从小到大,依次为:•(1):最小值(2):null(3):数字(整型,长整型,双精度)(4):字符串(5):对象/文档(6):数组(7):二进制数据(8):对象ID(9):布尔值(10):日期型(11):时间戳(12):正则表达式(13):最大值高级查询学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•查询分为普通查询和包装查询,我们上面演示的各种查询方式都是普通查询,如下我们再演示一个•db.fruitprice.find({apple:10}).sort({banana:1});•上述查询我们转换为包装形式的写法是:•db.fruitprice.find({$query:{apple:10},$orderby:{banana:1}});高级查询学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•我们的所有查询在发送到数据库端时,都被提前转换成了包装形式!包装形式就是额外使用了一些键,如上述的$query,$orderby。•1.$maxscan:integer指定查询时最多扫描文档的数量•2.$min:document查询的开始条件•3.$max:document查询的结束条件•4.$hint:document指定服务器使用哪些索引进行查询•5.$explain:boolean获取查询细节,如用到的索引,结果数量,耗时等,类似于关系数据库这边查看执行计划。并不会真正执行查询•6.$snapshot:boolean确保查询的结果是在查询执行那一刻的一致快照!这个在后面还会提到!获取一致结果学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台•从MongoDB中获取到数据后,通常会执行这种操作:对文档进行处理后,即时地更新到数据库中!对于大量文档有可能产生一个问题:前面提到,从数据库端调用游标的hasNext时,数据库默认会返回100条文档,开始操作。假设对于一个文档,增大了其大小,并且超高了MongoDB为文档设置的预留区域,这时将这条文档更新到数据库中,数据库没法将其放置在其原始位置上,只能将其移动,通常会移动到集合末尾!这样再次获取文档时,有可能又得到这条以被修改的文档!对这个问题方法是对查询结果进行快照!如果使用了上面提到的“$snapshop”选项,查询就是针对不变的集合视图运行的!这点我们只是描述一下,实际情况中可以不用担心了,因为MongoDB中,所有返回一组的查询实际都进行了快照。学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台小结•$where子句的使用•游标的使用方法学云为您提供高品质课件、学习督导服务、即时答疑、知识交易平台作业•熟悉$where子句的使用•熟悉游标的使用方法