zoukankan      html  css  js  c++  java
  • (5) MongoDB查询操作

    mongodb采用find来进行查询操作,根据传进去的参数不同,可以进行不同类型的操作。

    1. 最简单的查询

    首先,最简单的查询,当然是不带任何条件的查询,这在我们前面的例子中也看过了,如db.blog.find(),该查询将返回blog集合中所有的文档。

    2. 限定条件

    在关系型数据库(RDB)中,我们通过where来限定查询条件,如:

    select *

    from user

    where age =28

    我们来看看在mongodb中如何进行类似的操作:

    db.user.find({"age":28})

    mongodb的第一个参数用来指定要返回哪些文档,如,上面的例子表示,返回user集合中,age为28的所有文档。

    在RDB中,我们通过where A and B来指定多个条件,mongodb中的and也很简单,只需在第一个参数中列出多个键即可,如:

    db.user.find({"age":28,"name":"tian"})

    3. 返回指定的键

    在RDB中,我们可以通过指定列来我们需要的字段,在mongodb中,我们可以通过为find指定第二个参数,来指定我们需要返回的键。

    返回所有的字段有时是不必要的,甚至要浪费数据的传输量和客户端的解码时间。

    如:

    > db.user.insert({"_id":1,"name":"tian","age":28})
    > db.user.insert({"_id":2,"name":"jerry","age":36})
    > db.user.insert({"_id":3,"name":"harry","age":26})
    > db.user.find({},{"name":1})
    { "_id" : 1, "name" : "tian" }
    { "_id" : 2, "name" : "jerry" }
    { "_id" : 3, "name" : "harry" }

    我们发现,age这个键没有返回,但是_id这个键返回了,这是mongodb默认的。

    Note:在上面的find语句中,第一个参数为{},表示没有限定条件。

    有时候,集合里面的键比较多,如果我们一一列举显得有点罗嗦,这个时候,我们可以通过指定不需要返回的键,如:

    > db.user.find({},{"age":0})
    { "_id" : 1, "name" : "tian" }
    { "_id" : 2, "name" : "jerry" }
    { "_id" : 3, "name" : "harry" }

    将不需要的键指定为0,这样当集合的键比较多时,就可以省掉不少麻烦了。

    4. 其他查询条件

    除了前面一些简单的匹配外,mongodb还可以进行更加复杂的查询,我们通过跟RDB对比进行说明

    image

    跟RDB对比后,mongodb的用法就一目了然了。虽然mongodb的操作符没有像平常的比较运算符好记,但是mongodb的这些操作符也都是根据英文缩写,如$gt就是great than,$lte就是less than,所以也不算难记。

    5. 特殊的null

    null无论在哪里,都注定是特殊的一员,mongodb中的null也是一样。

    首先,null确实可以匹配自身,如:

    > db.user.insert({"_id":4,"name":"leon",age:null})

    > db.user.find({"age":null})
    { "_id" : 4, "name" : "leon", "age" : null }

    但是,null还会匹配不存在的键

    > db.user.insert({"_id":6,"name":"jim"})
    > db.user.find({"age":null})
    { "_id" : 4, "name" : "leon", "age" : null }
    { "_id" : 6, "name" : "jim" }

    我们看到,没有age这个键的文档也匹配上了。

    当然,我们也可以防止这种情况发生,那就是指定存在null值的键的文档才返回:

    > db.user.find({"age":{"$in":[null],"$exists":true}})
    { "_id" : 4, "name" : "leon", "age" : null }

    这个写法看上去很别扭,但是,没办法,mongodb没有提供类似$eq(equal)的操作符。

    6. 操作数组

    先看个简单的例子:

    > db.food.insert({"fruit":["apple","banana","peach"]})
    > db.food.find({"fruit":"apple"})
    { "_id" : ObjectId("500fe140ad99f95967489682"), "fruit" : [ "apple", "banana", "peach" ] }

    只要数组里面包含要匹配的值,就会匹配成功。

    有时候,我们需要查找数组中包含多个值的,就需要用到$all了。

    考虑这样一个集合

    { "_id" : ObjectId("500fe140ad99f95967489682"), "fruit" : [ "apple", "banana", "peach" ] }
    { "_id" : ObjectId("500fe349ad99f95967489683"), "fruit" : [ "cherry", "banana","apple" ] }
    { "_id" : ObjectId("500fe358ad99f95967489684"), "fruit" : [ "apple", "orange", "peach" ] }

    我们要找到既包含apple,又包含banana的文档:

    > db.food.find({"fruit":{"$all":["apple","banana"]}})
    { "_id" : ObjectId("500fe140ad99f95967489682"), "fruit" : [ "apple", "banana", "peach" ] }
    { "_id" : ObjectId("500fe349ad99f95967489683"), "fruit" : [ "cherry", "banana","apple" ] }

    我们还可以通过数组进行查找,需要注意的是,用数组查找就是完全匹配了,如:

    > db.food.find({"fruit":["apple","banana"]})
    > db.food.find({"fruit":["apple","banana","peach"]})
    { "_id" : ObjectId("500fe140ad99f95967489682"), "fruit" : [ "apple", "banana", "peach" ] }

    有时候需要根据数组个数来查找的,如

    > db.food.find({"fruit":{"$size":3}})

    RDB中经常用top来获取前几条数据,对于数组的前几个的获取,就需要用到$slice了,如:

    > db.food.find({},{"fruit":{"$slice":2}})
    { "_id" : ObjectId("500fe140ad99f95967489682"), "fruit" : [ "apple", "banana" ]}
    { "_id" : ObjectId("500fe349ad99f95967489683"), "fruit" : [ "cherry", "banana" ] }
    { "_id" : ObjectId("500fe358ad99f95967489684"), "fruit" : [ "apple", "orange" ]}

    可以看到,fruit中只返回了前两个值。

    也可以返回指定的返回的元素,如

    > db.food.find({},{"fruit":{"$slice":[2,4]}})

    这个语句是指,跳过前面的2个元素,返回3~4这2个元素。

    7.内嵌文档的查询

    所谓内嵌文档,就是指文档的值本身又是一个文档。

    假设有这样的一个文档:

    {

        "name”:

                    {

                      "first":"terry",

                       "last":"chen"

                     },

         "age":12

    }

    要寻找名字为terry chen的可以这样:

    > db.userinfo.find({"name":{"first":"terry","last":"chen"}})
    { "_id" : ObjectId("500fee69ad99f95967489687"), "name" : { "first" : "terry", "last" : "chen" }, "age" : 12 }

    但是有个问题就是如果我们把"first"键和"last"键位置放错了,或者我们在加入一个"middle"键,那么就没有办法找到该文档了。

    这就需要我们更改查询的策略,mongodb中用点表示查询内嵌的键:

    > db.userinfo.find({"name.first":"terry","name.last":"chen"})

    这样,即使将来加了"middle"键,依旧可以找到上面的文档。

    当内嵌文档更加复杂之后,我们就需要更多的技巧了,如,有文档:

    > db.blog.find()
    { "_id" : 1, "title" : "1st post", "comments" : [       {       "author" : "joe"
    ,       "score" : 3 },  {       "author" : "marry",     "score" : 6 } ] }

    我们要找到评论者为joe,且score>=5的文档,如果我们采用:

    > db.blog.find({"comments.author":"joe","comments.score":{"$gte":5}})
    { "_id" : 1, "title" : "1st post", "comments" : [       {       "author" : "joe"
    ,       "score" : 3 },  {       "author" : "marry",     "score" : 6 } ] }

    来查找,明显是错误的,因为它返回了刚才的文档,因为第一条评论匹配了author:joe,第二条评论匹配了score:6.

    要正确的指定一组条件,而不用指定每个键,要使用"$elemMatch":

    > db.blog.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gte":5}}}})

    "$elemMatch"将限定条件分组,仅当需要对一个内嵌文档的多个键操作时才会用到。

    8.$where查询

    $where子句可以执行任意JavaScript作为查询的一部分,这就使得查询几乎能做任何事。

    但是,它的性能比常规查询要慢很多,因为每个文档都要从BSON转换成JavaScript对象,然后通过$where表达式来运行,同时,还不能利用索引。

    因此,不是非常必要时,不要用$where子句。

    参考:mongodb权威指南

    备注:本节基本是《mongodb权威指南》第4章的笔记

  • 相关阅读:
    未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0或2.0.0.0
    解决本地调用office组件成功,但是发布到IIS中出现的错误(检索COM类工厂中CLSID为{00024500-0000-0000-C000-000000000046}的组件时失败)
    未能找到类型或命名空间名称“Coco”(是否缺少 using 指令或程序集引用)
    SQL截取字段字符串的方法
    C# 128位AES 加密解密 (转)
    检索 COM 类工厂中 CLSID 为 {13C28AD0-F195-4319-B7D7-A1BDAA329FB8} 的组件时失败,原因是出现以下错误: 80040154
    js 获取时间比较全,留备用(zhuan)
    windows之如何把iso文件转换为VHD文件
    python之三行代码发送邮件
    RobotFramework第二篇之web自动化
  • 原文地址:https://www.cnblogs.com/tian2010/p/2607465.html
Copyright © 2011-2022 走看看