查询(mongodb权威指南第4章)

  • 使用find或者findOne函数和查询文档对数据库执行查询
  • 使用$条件查询实现范围、集合包含、不等式和其他查询
  • 有些查询用查询文档,甚至$条件语句都不能表达,对于这种复杂的查询,可以用$where 子句,用强大的javasript来表达
  • 查询将会返回一个数据库游标,游标只有在你需要的时候才会惰性的批量返回文档
  • 还有很多针对游标执行的元操作,包括忽略一定数量的结果,或者限定返回结果的数量,还有对结果排序

4.1 find简介

 D:\java\mongodb-win32-i386-2.2.3\bin>mongo
MongoDB shell version: 2.2.3
connecting to: test
> show dbs;
local   (empty)
test    0.125GB
> use test;
switched to db test
> db.foo.find()
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
> db.foo.insert({"name":"king","age":20})
> db.foo.insert({"name":"king1","age":25})
> db.foo.insert({"name":"king2","age":21})
> db.foo.find()
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
> db.foo.find({"name":king})
Fri Mar 22 23:51:29 ReferenceError: king is not defined (shell):1
> db.foo.find({"name":"king"})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
> db.foo.find({"name":"king","age":20})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
>

  可以通过向查询文档加入多个键值对组合查询条件,解释为and

   空的查询文档{}会匹配集合的所有文档,要是不指定,默认就是{}

  4.1.1 指定返回的键

     可以通过find或者findOne的第二个参数指定想要的键。

 > db.foo.find({},{"name":1})        只返回name,_id总是被返回,即便没有指定也一样
ObjectId("5149af43ad11c9803e1781ea") }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb") }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king" }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1" }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2" }
> db.foo.find({},{"name":0})    剔除查询结果中的某个键值对
"_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "age" : 21 }
> db.foo.find({},{"name":1,"_id":0})  防止返回_id

}
{ "name" : "king" }
{ "name" : "king1" }
{ "name" : "king2" }
>

    4.1.2 限制

        数据库所关心的查询文档必须是常量。

4.2 查询条件

        范围、OR子句和取反

     4.2.1 查询条件

        比较操作符:“$lt”,“$lte","$gt","$gte"  "$ne

                            <     <=   >      >=      !=

  db.user.find({"birthday":{"$lt":start}})

 > db.foo.find()
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
> db.foo.find({"age":{"$gte":21,"$lte":25}})
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
> db.foo.find({"name":{"$ne":"king"}})
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
> db.foo.find({"age":{"$lte":25}})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }

   4.2.2 OR查询

      mongodb中有两种方式进行OR查询。

      "$in"可以用来查询一个键的多个值。  "$nin"  针对单个键做OR查询

 > db.foo.find({"age":{"$in":[21,25]}})
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }

> db.foo.insert({"name":234,"age":30})
> db.foo.find("name":{"$in":["king",234]})
Sat Mar 23 00:25:25 SyntaxError: missing ) after argument list (shell):1
> db.foo.find({"name":{"$in":["king",234]}})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c85c1127bab4493992959"), "name" : 234, "age" : 30 }

> db.foo.find({"name":"king"})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
> db.foo.find({"name":{"$in":["king"]}})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }

> db.foo.find({"name":{"$nin":"king"}})
error: { "$err" : "$nin needs an array", "code" : 13277 }
> db.foo.find({"name":{"$nin":["king"]}})
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
{ "_id" : ObjectId("514c85c1127bab4493992959"), "name" : 234, "age" : 30 }

 

      "$or"完成多个键值的任意给定值。接受一个包含所有可能条件的数组作为参数

 > db.foo.find({"$or":[{"name":"king"},{"age":20}]})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }

> db.foo.find({"$or":[{"name":{"$in":["king","king1"]}}]})
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }

     使用普通的AND查询时,尽可能用最少的条件来限定结果的范围

     OR型的相反:第一个条件进啊可能匹配更多的文档,这样最有效。

  4.2.3 $not

     这是个元条件句,即可以用在任何其他条件之上。

 > db.foo.find({"age":{"$mod":[5,1]}})
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }

> db.foo.find({"age":{"$not":{"$mod":[5,1]}}})
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c85c1127bab4493992959"), "name" : 234, "age" : 30 }

  4.2.4 条件句的规则

4.3 特定与类型的查询

     4.3.1 null

  •          匹配自身
  • 匹配不存在的
  • 如果之匹配键值为null的文档,纪要检查改建的值是否为null,还要通过"$exists"条件判定改建已经存在

 > db.foo.insert({"name":null,"age":28})
> db.foo.find()
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514c7dce127bab4493992956"), "name" : "king", "age" : 20 }
{ "_id" : ObjectId("514c7dda127bab4493992957"), "name" : "king1", "age" : 25 }
{ "_id" : ObjectId("514c7de3127bab4493992958"), "name" : "king2", "age" : 21 }
{ "_id" : ObjectId("514c85c1127bab4493992959"), "name" : 234, "age" : 30 }
{ "_id" : ObjectId("514d0c6be30a115bf216e111"), "name" : null, "age" : 28 }


> db.foo.find({"name":null})
{ "_id" : ObjectId("5149af43ad11c9803e1781ea"), "bar" : "baz" }
{ "_id" : ObjectId("5149d1ffad11c9803e1781eb"), "xx" : 2 }
{ "_id" : ObjectId("514d0c6be30a115bf216e111"), "name" : null, "age" : 28 }


> db.foo.find({"name":{"$in":[null],"$exists:true"}})
Sat Mar 23 10:01:50 SyntaxError: missing : after property id (shell):1


> db.foo.find({"name":{"$in":[null],"$exists":true}})
{ "_id" : ObjectId("514d0c6be30a115bf216e111"), "name" : null, "age" : 28 }
>

     4.3.2 正则表达式

     4.3.3 查询数组

        绝大多数情况下可以这样理解:每一个元素都是整个键的值

 > db.fruit.insert({"fruit":["apple","banana","peach"]})
> db.fruit.insert({"fruit":["apple","banana","peach"]})
> db.fruit.find()
{ "_id" : ObjectId("514d0f6ae30a115bf216e112"), "fruit" : [ "apple", "banana", "
peach" ] }
{ "_id" : ObjectId("514d0f72e30a115bf216e113"), "fruit" : [ "apple", "banana", "
peach" ] }
> db.fruit.find({"fruit":"apple"})
{ "_id" : ObjectId("514d0f6ae30a115bf216e112"), "fruit" : [ "apple", "banana", "
peach" ] }
{ "_id" : ObjectId("514d0f72e30a115bf216e113"), "fruit" : [ "apple", "banana", "
peach" ] }

  这个查询相当于我们用了一个如下的文档(不合法的)进行的查询:

  {”fruit“:”apple","fruit":"banana"}

  • $all  需要通过多个元素来匹配数组

 > db.fruit.find()
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }
> db.fruit.find({fruit:{$all:["apple","banana"]}})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }
> db.fruit.find({fruit:{$all:["banana","apple"]}})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }
>

> db.fruit.find({fruit:"apple"})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }
> db.fruit.find({fruit:{$all:["apple"]}})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

    也可以使用完整的数组精确地匹配。但是,精确匹配对于有缺少或者冗余元素的情况下就不灵了。

 > db.fruit.find({"fruit":["apple","banana","peach"]})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }


> db.fruit.find({"fruit":["apple","banana"]})


> db.fruit.find({"fruit":["banana","apple","peach"]})
>

    要想查询数组指定位置的元素,需要使用key.index语法制定下标,下标从0开始

 > db.fruit.find({"fruit.2":"peach"})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
>
  •    $size 查询指定长度的数组
 > db.fruit.find({"fruit":{"$size":3}})
{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }
{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

 

 

 

  • $slice find的第二个参数是可选的,可以指定返回哪些键,$slice返回数组的一个子集合

       可以接受偏移量和要返回的元素数量,来返回中间的结果

       除非特别声明,返回文档中的所有键

      

 

  4.3.4查询内嵌文档

     有两种发方法:查询整个文档或者只针对其键值对进行查询

    查询整个内嵌文档与普通查询完全相同:

  

4.4 $where 查询

    用它可以执行任意javascript作为查询的一部分,是得查询几乎能做任何事情。

   最典型的应用就是比较文档中的两个键的值是否相等。

   避免使用。

4.5 游标

  

4.6 游标内幕

 

   

 

       

    

    

转载于:https://my.oschina.net/kingwjb/blog/115289

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值