zoukankan      html  css  js  c++  java
  • MongoDB的查询

    一、Find操作

    二、分页和排序

    三、游标的使用

     

    一、Find查询

    事前准备:插入如下数据

    db.Students.insert([
    { _id:1,  name:"Zhao", age:25, country:"USA", books:["JS","C++","EXTJS","MONGODB"]},
    { _id:2, name:"Qian",age:22, country:"USA", books:["PHP","JAVA","EXTJS","C++"]},
    { _id:3,name:"Sun",age:26, country:"USA", books:["JS","JAVA","C#","MONGODB"]},
    { _id:4, name:"Li",age:27,country:"China",books:["JS","JAVA","EXTJS","MONGODB"]},
    { _id:5,name:"Zhou", age:30,country:"China",books:["JS","C#","PHP","MONGODB"]},
    { _id:6, name:"Wu", age:27, country:"Japan", books:["JS","JAVA","C++","MONGODB"]},
    { _id:7, name:"Zheng", age:27, country:"UK", books:["JS","JAVA","EXTJS","PHP"]},
    { _id:8, name:"Wang", age:26,  country:"Korea",books:["JS","C#","EXTJS","MONGODB"]}
    ]) 

    1.指定返回的键

      db.[文档名].find ({条件},{键指定})

      1.1 查询出所有数据的指定键(name ,age ,country)

    db.Students.find({},{name:1,age:1,country:1,_id:0})

    ※条件不写就是查询全部

    ※需要查询的就在键后指定为1,不用就指定为0(感觉只要想查的键后面有值不见得非得是1

    ※如果不指定显示=_id:0,那查询过程都是带有_id

    例:查询所有学生的姓名和国家
    > db.Students.find({},{name:1,country:1})
    { "_id" : 1, "name" : "Zhao", "country" : "USA" }
    { "_id" : 2, "name" : "Qian", "country" : "USA" }
    { "_id" : 3, "name" : "Sun", "country" : "USA" }
    { "_id" : 4, "name" : "Li", "country" : "China" }
    { "_id" : 5, "name" : "Zhou", "country" : "China" }
    { "_id" : 6, "name" : "Wu", "country" : "Japan" }
    { "_id" : 7, "name" : "Zheng", "country" : "UK" }
    { "_id" : 8, "name" : "Wang", "country" : "Korea" }
    >
    

    2.查询条件

    比较操作符

    意义

    举例

    $lt

    <

    查询出id小于5的学生

    > db.Students.find({_id:{$lt:5}},{})

    $lte

    <=

    查询出年龄小于等于25岁之间的学生

    > db.Students.find({age:{$lte:25}},{})

    $ne

    !=

    查询出国家不是中国的学生

    > db.Students.find({country:{$ne:"China"}},{})

    $gt

    >

    查询所有年纪大于27岁的,中国学生名字

    > db.Students.find({age:{$gt:27}},{name:1,country:1,age:1})

    { "_id" : 5, "name" : "Zhou", "age" : 30, "country" : "China" }

    $gte

    >=

    同上

     

    3.包含或不包含

    较操作符

    意义

    举例

    $in

    包含

    查询国家是中国和美国的学生

    > db.Students.find({country:{$in:["China","USA"]}},{})

    $nin

    不包含

    查询年龄不是27岁的学生

    > db.Students.find({age:{$nin:[27]}},{})

     

    4.OR查询

    较操作符

    意义

    举例

    $or

    包含

    查询年龄小于27岁,或者国家是美国的学生

    >db.Students.find({$or:[{age:{$lt:27}},{country:"USA"}]},{})

    查询年龄大于等于30岁,或者国家是不是美国的学生

    >db.Students.find({$or:[{age:{$gte:30}},{country:{$nin:["China"]}}]},{})

     

    5.Null

    为所有美国学生添加性别属性为男性(M

    > db.Students.update({country:"USA"},{$set:{sex:"M"}},false,true)
    

    查询所有sex属性为null的学生

    > db.Students.find({sex:{$in:[null]}},{name:1,country:1})

    6.正则查询

    查询出名字中存在”Zh”的学生的信息

    > db.Students.find({name:/Zh/},{})
    { "_id" : 1, "name" : "Zhao", "age" : 25, "country" : "USA", "books" : [ "JS", "C++", "EXTJS", "MONGODB" ], "sex" : "M" }
    { "_id" : 5, "name" : "Zhou", "age" : 30, "country" : "China", "books" : [ "JS", "C#", "PHP", "MONGODB" ] }
    { "_id" : 7, "name" : "Zheng", "age" : 27, "country" : "UK", "books" : [ "JS", "JAVA", "EXTJS", "PHP" ] }

    7.$not的使用

    $not$nin的区别是$not可以用在任何地方儿$nin是用到集合上的

    查找出名字中不存在“Zh”的学生信息

    > db.Students.find({name:{$not:/Zh/}},{})
    { "_id" : 2, "name" : "Qian", "age" : 22, "country" : "USA", "books" : [ "PHP","JAVA", "EXTJS", "C++" ], "sex" : "M" }
    { "_id" : 3, "name" : "Sun", "age" : 26, "country" : "USA", "books" : [ "JS", "JAVA", "C#", "MONGODB" ], "sex" : "M" }
    { "_id" : 4, "name" : "Li", "age" : 27, "country" : "China", "books" : [ "JS", "JAVA", "EXTJS", "MONGODB" ] }
    { "_id" : 6, "name" : "Wu", "age" : 27, "country" : "Japan", "books" : [ "JS", "JAVA", "C++", "MONGODB" ] }
    { "_id" : 8, "name" : "Wang", "age" : 26, "country" : "Korea", "books" : [ "JS","C#", "EXTJS", "MONGODB" ] }

    8.数组查询$allindex应用

    查询所有拥有JSPHP书籍的同学

    > db.Students.find({books:{$all:["JS","PHP"]}},{})
    { "_id" : 5, "name" : "Zhou", "age" : 30, "country" : "China", "books" : [ "JS", "C#", "PHP", "MONGODB" ] }
    { "_id" : 7, "name" : "Zheng", "age" : 27, "country" : "UK", "books" : [ "JS", "JAVA", "EXTJS", "PHP" ] }

    查询第三本书是C#的同学

    > db.Students.find({"books.2":"C#"},{})
    { "_id" : 3, "name" : "Sun", "age" : 26, "country" : "USA", "books" : [ "JS", "JAVA", "C#", "MONGODB" ], "sex" : "M" } 

    上面那个使用index来查询的例子中,"books.2"一定要用""包含起来

    9.查询指定长度数组$size

    它不能与比较查询符一起使用(这是弊端)

    插入一条book数组有两本数的同学

    > db.Students.insert({_id:9,name:"Xu",age:26,country:"Japan",books:["C#","PHP"]})
    WriteResult({ "nInserted" : 1 })

    查询只有两本书的同学

    > db.Students.find({books:{$size:2}},{})
    { "_id" : 9, "name" : "Xu", "age" : 26, "country" : "Japan", "books" : [ "C#", "PHP" ] }

    查询名字是“Li”的喜欢的书的数量

    > var person = db.Students.find({name:"Li"})
    > while(person.hasNext()){ obj = person.next(); print(obj.books.length) }
    

    10.$slice操作符返回文档中指定数组的内部值

    查询名字为“Wang”书架中第1~3本书

    > db.Students.find({name:"Wang"},{books:{$slice:[0,3]}})
    { "_id" : 8, "name" : "Wang", "age" : 26, "country" : "Korea", "books" : [ "JS", "C#", "EXTJS" ] }
    

    查询出最后一本书

    > db.Students.find({name:"Wang"},{books:{$slice:-1}})
    { "_id" : 8, "name" : "Wang", "age" : 26, "country" : "Korea", "books" : [ "MONGODB" ] }  

    11.文档查询

    添加一个对象数组到“Li”同学,记录“Li”同学的成绩

    > var li = [{
    
    ... subject :"Math",
    
    ... score: 90
    
    ... },{
    
    ... subject :"English",
    
    ... score:85
    
    ... },{
    
    ... subject :"History",
    
    ... score:95
    
    ... }]
    
    > db.Students.update({name:"Li"},{$set:{school:li}})
    
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    
    > db.Students.find({name:"Li"},{})
    
    { "_id" : 4, "name" : "Li", "age" : 27, "country" : "China", "books" : [ "JS", "JAVA", "EXTJS", "MONGODB" ],
    
     "school" : [{ "subject" : "Math", "score" : 90 },{ "subject" : "English", "score" : 85 }, { "subject" : "History", "score" : 95 }]
    }
    
    >
    

    查询参加了数学考试,并且分数为90的同学

    .绝对匹配可以

    > db.Students.find({school:{subject:"Math",score:90}},{_id:0,name:1})
    { "name" : "Li" }  

    但是问题存在如下:

    条件顺序变化时候,

    > db.Students.find({school:{score:90,subject:"Math"}},{_id:0,name:1})
    > --查不到东西-- 

    条件数目不一致的时候,也同样查不到

    .为了解决顺序的问题我可以用对象“.

    > db.Students.find({"school.subject":"Math","school.score":90},{name:1})
    { "_id" : 4, "name" : "Li" }

    这种方式支持顺序的变化,但是也同样存在问题,那就是匹配的问题,条件不是作为一对条件来进行匹配的

    例如:

    > db.Students.find({"school.subject":"Math","school.score":85},{name:1})
    { "_id" : 4, "name" : "Li" } 

    这里的85分是英语成绩

    .正确做法单条条件组查询$elemMatch

    > db.Students.find({school:{$elemMatch:{subject:"Math",score:90}}},{name:1})
    { "_id" : 4, "name" : "Li" }
    > db.Students.find({school:{$elemMatch:{score:90,subject:"Math"}}},{name:1})
    { "_id" : 4, "name" : "Li" }
    > db.Students.find({school:{$elemMatch:{subject:"Math"}}},{name:1})
    { "_id" : 4, "name" : "Li" }
    >
    

    二、分页与排序

    1.Limit返回指定的数据条数

    查询出Student文档中前5条数据

    > db.Students.find().limit(5)
    2.Skip返回指定数据的跨度
    查询出persons文档中3~8条的数据
    > db.Students.find().limit(5).skip(2)
    

    3.Sort返回按照年龄排序的数据[1,-1]

    查询所有数据,按照年龄排序

    正序
    > db.Students.find({},{_id:0,age:1,name:1}).sort({age:1})
    { "name" : "Qian", "age" : 22 }
    { "name" : "Zhao", "age" : 25 }
    { "name" : "Sun", "age" : 26 }
    { "name" : "Wang", "age" : 26 }
    { "name" : "Xu", "age" : 26 }
    { "name" : "Wu", "age" : 27 }
    { "name" : "Zheng", "age" : 27 }
    { "name" : "Li", "age" : 27 }
    { "name" : "Zhou", "age" : 30 }
    倒序
    > db.Students.find({},{_id:0,age:1,name:1}).sort({age:-1})
    { "name" : "Zhou", "age" : 30 }
    { "name" : "Wu", "age" : 27 }
    { "name" : "Zheng", "age" : 27 }
    { "name" : "Li", "age" : 27 }
    { "name" : "Sun", "age" : 26 }
    { "name" : "Wang", "age" : 26 }
    { "name" : "Xu", "age" : 26 }
    { "name" : "Zhao", "age" : 25 }
    { "name" : "Qian", "age" : 22 }
    >
    

    skip性能不好,可以采用插入时间的做法来弥补,具体方法如下:

    1.在每一个记录后面都加入一个插入时间的键值对

    2.每次取数据的时候都把取出的最后一个数据的时间保存下来,再传给下一次查询

    3.使用 db.persons.find({date:{$gt:日期数值}}).limit(取出的数据数目)比较查询取出要分页的数据

      

    三、游标和其他知识

    1.利用游标来查询数据

        var  persons = db.persons.find();
        while(persons.hasNext()){
        obj = persons.next();
              print(obj.name)
         }
    

    2.游标几个销毁条件  

        客户端发来信息叫他销毁

        游标迭代完毕

        默认游标超过10分钟没用也会别清除

     

    3.查询快照

        快照后就会针对不变的集合进行游标运动了,看看使用方法.

        db.persons.find({$query:{name:”Jim”},$snapshot:true})

     

    为什么用快照,以为MongoDB在进行更新的时候,例如添加一些键值对,那么MongoDB的处理不会在原来的索引位置上进行更新操作,而是会把

    更新之后的数据,放在末尾,那么就导致了前后两次进行查询时候相同索引对应不同数据的情况

     

    补充:

    高级查询选项 

        $where  

        $query

        $orderby

        $maxsaninteger 最多扫描的文档数

        $mindoc  查询开始

        $maxdoc  查询结束

        $hintdoc   使用哪个索引

        $explain:boolean  统计

        $snapshot:boolean 一致快照

  • 相关阅读:
    JavaScript tips:innerHTML与document.write的差异
    JavaScript tips:window.onload与$(document).ready()的差异
    剑指offer:重建二叉树
    算法:数组去重
    JavaScript tips:Function调用模式对this的影响
    P1217 [USACO1.5]回文质数 Prime Palindromes
    HDU 1002 A + B Problem II
    单片机及其工作原理粗略介绍
    Markdown格式及语法
    Kubernetes入门(三)——使用Deployment运行一个无状态应用
  • 原文地址:https://www.cnblogs.com/dcz2015/p/5251309.html
Copyright © 2011-2022 走看看