MongoDB学习笔记(三)

查询

   1.db.c.find() :返回集合c中所有的内容
   
   2.条件查询:
      例子
      1).要查询所有的"age"的值为27的文档
         db.users.find({"age":27})
      2).查询 "username"的值为joe 的文档
         db.users.find({"username":"joe"})
      3).查询age是27 且 username是joe的文档
         db.users.find({"username":"joe","age":27})
         
   3.返回指定的键值对(根据find()的第二个参数)
      例子
      1).查询用户集合的username 和 email
         db.user.find({},{username:1,email:1})
           注意点:
             1:代表需要
             0:代表不需要
             _id这个键总是被返回
      
      2). 查询用户集合的文档 不希望返回含有sex的键
    db.user.find({},{"sex":0})
    也可以防止生成_id
     
     
    4.查询条件
       1).$lt、$lte、$gt、$gte、$ne
          <、<=、>、>=、不等于
       例子:
        1).查找2007年1月1日前注册的人
        start = new Date("01/01/2007")
        db.users.find({"age":{"$lt":start}})
        2). 查询用户年龄在18-30的用户
        db.users.find({"age":{"$gte":18,"$lte":30})
        3).查询名字不是“joe”的用户
        db.users.find({"username":{"$ne":"joe"}})
     
     5.OR查询
        1)$in
           1)例子一
           查找中奖号码 是 725或255或155 的所有号码编号           
           dao.raffle.find({"ticket_no":{"$in":[725,255,155]}})
        2)例子二
        可以是不同的类型
        dao.users.find({"users":{"$in":["abc",1234]}})
         
       2).$nin :与$in 相反
        1).查询没中奖的用户
        dao.raffle.find({"ticket_no":{"$nin":[725,255,155]}})
       
       3).$or
           1).dao.raffle.find({"$or":[{"ticket_no":{"$in":[725,255,155]}},{"winner":true}]})
           
       4).$not
           1).$mod
              dao.find({"id_num":{"$mod":[5,1]}})
                说明 $mod 会将查询的值 除以第一个数(5) 若余数等于第二个
                则返回该数 该查询返回的结果是:1,6,11,16...
                
           2)返回以上相反地结果
              dao.find({"$id_num":{"$not":{"$mod":[5,1]}}})
              
     6.条件语句的规则
        1):条件句是内层文档的键、而修改器则是外层文档的键  
        2):可以对一个键应用多个条件
         db.users.find({"age":{"$lt":30,"$gt":20}})
        3):一个键不能有多个修改器
         错误写法:{"$inc":{"age":1},"$set":{"age":40}}
         
     7.null
       它不但能够匹配自身 而且能匹配"不存在"
       如果仅仅想要匹配键值为null的文档
       db.c.find({"z":{"$in":[null],"$exists":true}})
       
     8.正则表达式
       正则表达式能够灵活有效的匹配字符串
         例一
         db.users.find({"name",/joe/i})
         
      9.查询数组
        db.food.insert({"fruit":["apple","banana","peach"]})
        查询
        db.food.find({"fruit":"banana"})
        
        1).$all
           db.food.insert({"_id":1,"fruit":["apple","banana","peach"]})
           db.food.insert({"_id":2,"fruit":["apple","kumquat","orange"]})
           db.food.insert({"_id":3,"fruit":["cherry","banana","apple"]})
           
           db.food.find({"fruit":{$all:["apple","banana"]}})
           db.food.find({"fruit":"apple"}) 等价于 db.food.find({"fruit":{$all:"apple"}})
       
           精确匹配  
           db.food.find({"fruit":["apple","banana","peach"]})
           
        2).$size
           db.food.find({fruit:{$size:3}}) 
           对于key来说 加引号和不加一个样(js规定的)
             注意:$size 不能和其他的查询子句组合 例如 $gt
             解决以上办法:可以采用以下技巧
             
             db.food.insert({fruit:["orange","apple","peach"],size:3})
 
             db.food.update({},{$push:{fruit:"banana"},$inc:{size:1}})
             
             db.food.findOne({size:{$gt:3}})
             这个技巧$addToSet 不能用
             
             
         3).$slice
          db.blog.findOne(criteria,{"comments":{$slice:10}}) 查询记录的前10条评论
          db.blog.findOne(criteria,{"comments":{$slice:-10}}) 查询记录的末10条评论
          db.blog.findOne(criteria,{"comments":{$slice:[23,10]}})
          第24条开始 总数是10天 不足10条 就到末尾
            
         4).查询内嵌文档  
          {
          name:{
          first:"joe",
          last:"jamea"
          },
          age:45
          }
         
          正确写法:db.user.find({name:{first:"joe",last:"jamea"}})
          错误写法:db.user.find({name:{last:"jamea",first:"joe"}})
          注意顺序不能错 元素也不能少
          加入加个middle-name 那么第一种写法也是错误的
          db.user.find({name:{first:"joe",middle:"XXXX",last:"jamea"}})
         
          保险写法:
          db.user.find({"name.first":"joe","name.last":"jamea"})
         
         
          比较复杂的一种内嵌文档处理
          {
          content:"......",
          "comments":[
          {
          "author":"joe",
          "score":3,
          "comment":"nice posts"
          },
          {
          "author":"marry",
          "score":6,
          "comment":"terriable posts"
          }
          ]
          }
         
          查询joe 5分以上的评论
          2种错误写法:
           db.blog.find({comments:{author:"joe",score:{$gte:5}}})
            错误原因:文档不匹配
           
           db.blog.find({"comments.author":"joe","comments.score":{$gte:5}})
             错误原因:"comments.author":"joe" 数组第一项匹配
                      "comments.score":{$gte:5} 数组第二项匹配 
                      总的匹配上了 其实它并没有匹配上
           
            正确写法
            db.blog.find({"comments":{$elemMatch:{author:"joe",score:{$gte:5}}}})
                $elemMatch:将限定条件进行分组
                
          5).$where 查询
           查询文档中有两个键的值是否相等 相等返回文档
           db.foo.insert({banana:1,apple:2,peach:2})          
           db.foo.insert({banana:1,peach:3,apple:2}) 
           
           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;
           }})
           
           
           $where 不仅可以用函数 也能用表达式
           db.foo.find({"$where":"this.x+this.y==10"})
           db.foo.find({"$where":"function(){return this.x+this.y==10}}")
           
           不是必要要避免使用$where
           
           
          10.游标
          for(i =0 ;i<100;i++){
          db.c.insert({x:1});
          }
         
          var cursor = db.c.find();
         
          while(cursor.hasNext()){
          obj = cursor.next();
          //do something
          }
         
          游标还实现了 迭代器借口 所以可以用 forEach(fn)
          cursor.forEach(function(x){println(x.name)})
         
          调用find的时候 shell并不立即查询数据库
          var cursor = db.foo.find().sort({"x":1}).limut(1).skip(10);
          var cursor = db.foo.find().limut(1).sort({"x":1}).skip(10);
          var cursor = db.foo.find().skip(10).sort({"x":1}).limut(1);
          当执行cursor.hasNext()获取前100个结果 或者前4MB数据
         
          limit:限制返回结果
          db.c.find().limit(3)
          最多只返回3个结果 
         
          skip:忽略前面几个匹配的文档
          db.c.find().skip(3)
          略过前面3个匹配文档,然后返回余下的文档,如果匹配的
          文档少于3个 则不会返回任何文档
         
          sort:排序
          db.c.find().sort({username:1,age:-1})
          按username那么升序 age降序排序
         
          这3个一起使用可以弄分页
          业务需求:搜索MP3 每页50个结果 按价格降序
          第一页: db.stock.find({desc:"Mp3"}).limit(50).sort({"price":-1})
          点击下一页
            db.stock.find({desc:"Mp3"}).skip(50).limit(50).sort({"price":-1})
            略过前几条 对性能要求比较高 少用...
         
         11.不用skip进行分页
         
          用skip
          var page1 = db.foo.find(query).limit(100)
          var page2 = db.foo.find(query).skip(100).limit(100)
          var page3 = db.foo.find(query).skip(200).limit(100)
          ...
           
          不用skip
          var page1 = db.foo.find().sort({"date",-1}).limit(100)
          var latest = null
          while(page1.hasNext()){
          latest = page1.next();
          display(latest);
          }
           
          var page2 = db.foo.find({date:{$gt:latest.date}}).sort({"date",-1}).limit(100)
           
           
        12.随机选取文档
        方法一:
        var total = db.foo.count()
        var random =Math.floor(Math.random()*total)
        db.foo.find().skip(random).limit(1)
       
        方法二:
        db.people.insert({"name":"joe","random":Math.random()})
        db.people.insert({"name":"zhangsan","random":Math.random()})
        db.people.insert({"name":"wangjie","random":Math.random()})
       
        var random = Math.random();
       
        var res = db.people.find({"random":{"$gt":random}})
       
        if(res == null)
         res = db.people.find({"random":{"$lte":random}})
       
        13 高级查询
        14 获得一致结果
          需要使用:$snapshot
       
          15:游标内幕
            数据库10分钟后自动消失  需要程序手动的去提醒数据库别让游标过期 
                

你可能感兴趣的:(mongo,NoSQL)