`
onelark
  • 浏览: 32370 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

MongoDB权威指南(3)- 查询

 
阅读更多

1.find方法介绍

在不传入参数的情况下,find方法缺省使用{}做参数,它匹配所有的document。

我们可以传入一个查询document给find方法来限制输出,如:查找年龄为27的用户

>  db.users.find({ " age "  :  27 })

一个查询document里可以包括多个条件,如:查询年龄为27并且名字叫joe的用户

>  db.users.find({ " username "  :  " joe "  " age "  :  27 })

条件之间都是And关系。

指定查询返回的内容

有时候我们并不需要返回document里所有的key/value对,我们可以给find(或findOne)方法传入第二个参数来指定返回哪些key的值。

比如:我们只想要用户的名字和Email

>  db.users.find({}, { " username "  :  1  " email "  :  1 })
{
        " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523620 " ),
        " username "  :  " joe " ,
        " email "  :  " joe@example.com " 
}

"_id"键总是会被返回。

如果想指定不想返回的key,如:返回除了fatal_weakness以外的key的值

>  db.users.find({}, { " fatal_weakness "  :  0 })

用这个方法可以把缺省返回的"_id"给排除掉

>  db.users.find({}, { " username "  :  1  " _id "  :  0 })
{
" username "  :  " joe " ,
}

限制

查询document里边key的值对数据库来说必须是个常量,假如collection里边有两个key,一个叫int_stock一个叫num_sold,

如果我们想查询这两个key相等的document,下边的查询是行不通的

>  db.stock.find({ " in_stock "  :  " this.num_sold " })  //  doesn't work

2.查询条件

"$lt", "$lte", "$gt", 和"$gte"分别对应<,<=,>,>=

如:查询年龄在18到30之间的用户

>  db.users.find({ " age "  : { " $gte "  :  18  " $lte "  :  30 }})

“$ne" 不等于,可以用于任意类型的数据

如,查找名字不叫joe的用户

>  db.users.find({ " username "  : { " $ne "  :  " joe " }})

OR查询

mongoDB里有两种使用OR的方法,如果是一个key对应的多个值,可以用"$in",还有个”or"是一种更通用的方法。

如:我们在进行一个抽奖活动,ticket No是725,542,390的三个中奖了,我们可以这样把这三个document查出来

>  db.raffle.find({ " ticket_no "  : { " $in "  : [ 725  542  390 ]}})

"$in"里边指定的值可以是不同的数据类型

与"$in"相反的操作就是"$nin”,返回指定的key的值不存在于数组里边的document,

>  db.raffle.find({ " ticket_no "  : { " $nin "  : [ 725  542  390 ]}})

上边的查询返回没中奖的所有ticket。

如果要在多个key的查询条件之间建立Or关系就得用"$or",如,查询彩票号码为725542390  或者winner为true的document

>  db.raffle.find({ " $or "  : [{ " ticket_no "  : { " $in "  : [ 725  542  390 ]}},{ "winner "  :  true }]})

$not

"$not"可以应用于上边说的所有的条件操作符上,举个例子之前我们先看下求余(取模)操作符"$mod","$mod"指定一个整数数组做为key的值,

里边两个数字,第一个是对其求余的数字,第二个是余数。比如,我们要找id_num的值对5求余,余数为1的document

>  db.users.find({ " id_num "  : { " $mod "  : [ 5  1 ]}})

现在我们使用$not,如果找id_num对5求余后余数不为1的document

>  db.users.find({ " id_num "  : { " $not "  : { " $mod "  : [ 5  1 ]}}})

规律

回头再看下前一章的更新修饰符,就会发现同样是$打头的符号,它和本章说的查询条件符号的位置是不一样的,

在查询里,"$lt"属于内层document,而更新的时候"$inc"是外层document的key。

一个key上可以有多个查询条件,却不能有多个更新。

查询年龄为20到30的用户可以这样做

>  db.users.find({ " age "  : { " $lt "  :  30  " $gt "  :  20 }})

但是却没有下边这种更新修饰符

{ " $inc "  : { " age "  :  1 },  " $set "  : {age :  40 }}

3.特殊类型查询

null

null同时匹配自身和不存在的key,

>  db.c.find()
 " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523621 " ),  " y "  :  null  }
 " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523622 " ),  " y "  :  1  }
 " _id "  : ObjectId( " 4ba0f148d22aa494fd523623 " ),  " y "  :  2  }

如果要查找y为null的document

>  db.c.find({ " y "  :  null })
 " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523621 " ),  " y "  :  null  }

查找key为null的document时,缺少此key的所有document也会返回

>  db.c.find({ " z "  :  null })
 " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523621 " ),  " y "  :  null  }
 " _id "  : ObjectId( " 4ba0f0dfd22aa494fd523622 " ),  " y "  :  1  }
 " _id "  : ObjectId( " 4ba0f148d22aa494fd523623 " ),  " y "  :  2  }

如果想查找key存在并且为null的document,就要用"$exists"符号,

>  db.c.find({ " z "  : { " $in "  : [ null ],  " $exists "  :  true }})

这个办法看起来比较笨,没办法,我们没有"$eq"条件符号。

正则表达式

查找名字叫joe,但是忽略大小写的document

>  db.users.find({ " name "  :  / joe / i})

mongoDB使用Perl Compatible Regular Expression (PCRE)来匹配正则表达式,所有PCRE允许的语法都可以在mongoDB里使用。

查询数组

查询数组很简单,通常情况下,数组的每个元素的值都能看作key的值。

例如,我们有一些水果

>  db.food.insert({ " fruit "  : [ " apple "  " banana "  " peach " ]})

我们查找水果里有香蕉的ducoment

>  db.food.find({ " fruit "  :  " banana " })

用起来就好像我们有这么一个document在

{ " fruit "  :  " apple " , " fruit "  :  " banana "  " fruit "  :  " peach " }

当然,上边这个document是不合法的。

$all

如果要匹配数组里的多个元素,就要用“$all”。

例如,我们有这样一个collection

>  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 " ]})

要查询既有apple又有banana的document

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

$all的值里边的元素是没有顺序的,只要目标包含里边的每个元素即可,如果不使用$all,就会执行精确的匹配检查。

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

上边这个查询会匹配第一个document

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

这个查询就不会匹配第一个document

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

同样,这个查询也不会匹配第一个document

如果要匹配数组里指定的元素,就要使用key.index这种语法

>  db.food.find({ " fruit.2 "  :  " peach " })

index 是从0开始索引的

$size

按照数组中元素的个数查询

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

$size 不能和比较条件符号(如$gt)联合使用

$slice操作符

上边曾经提到过,使用find方法的第二个参数,指定哪些键值会被返回,$slice操作符可以返回数组元素的一个子集。

例如,查找博客和它的前10条评论

>  db.blog.posts.findOne(criteria, { " comments "  : { " $slice "  :  10 }})

或者,如果想要后10条评论的话

>  db.blog.posts.findOne(criteria, { " comments "  : { " $slice "  :  - 10 }})

也可以返回中间的一段结果

>  db.blog.posts.findOne(criteria, { " comments "  : { " $slice "  : [ 23  10 ]}})

上边的查询跳过前23个元素,返回第24个到第34个元素。

查询嵌入的document

查询嵌入的整个document和普通的查询没有差别,比如我们有这样一个document

{
        " name "  : {
                " first "  :  " Joe " ,
                " last "  :  " Schmoe " 
        },
        " age "  :  45 
}

那么我们就可以这样查询名字叫Joe Schmoe的人

>  db.people.find({ " name "  : { " first "  :  " Joe "  " last "  :  " Schmoe " }})

如果Joe要加一个middle name,这个查询就不行了,这种查询必须匹配整个嵌入的document,而且key是有顺序的。

我们可以用.来直接查询嵌入的key。

>  db.people.find({ " name.first "  :  " Joe "  " name.last "  :  " Schmoe " })

点号在查询用document里就被解释为“通向嵌入的document”,所以document的key里边不能包含点号。

$where 查询

$where子句允许你在查询里执行arbitary javascript,使你几乎可以在查询中做任何事情。

最常见的例子就是比较document里边两个key的值。举个例子,我们有个list,我们想返回里边的key的值里有相等的document

(随便哪两个key,只要它们的value相等即可)。

>  db.foo.insert({ " apple "  :  1  " banana "  :  6  " peach "  :  3 })
>  db.foo.insert({ " apple "  :  8  " spinach "  :  4  " watermelon "  :  4 })

第二个document里,菠菜和西瓜的值是相等的,这个应该返回,这个使用$条件查询符号是做不到的。

>  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 ;
... }});

如果函数返回true,那么这个document就会作为结果集的一部分被返回。

刚才我们定义了一个函数,给$where查询指定一个字符串是一样的效果

>  db.foo.find({ " $where "  :  " this.x + this.y == 10 " })
>  db.foo.find({ " $where "  :  " function() { return this.x + this.y == 10; } " })

这两个查询是等价的。

如非必要,尽量不要使用$where查询,$where查询比一般的查询慢很多,每个document都必须从BSON转换为一个javascript对象,

然后执行$where表达式。而且,索引也不能使用。你可以通过组合使用$where查询和非$where查询来降低使用它的代价。

4.游标

find方法使用游标返回查询结果,游标的客户端实现使你可以对最终结果做很多的控制。在shell里创建一个游标很简单,往collection里放些document,

执行查询,将返回结果指派给一个本地变量即可。

>   for (i = 0 ; i < 100 ; i ++ ) {
... db.c.insert({x : i});
... }
>   var  cursor  =  db.collection.find();

你可以使用next方法来遍历结果,使用hasNext方法来检查有没有下一个,典型的循环如下

>   while  (cursor.hasNext()) {
... obj 
 =  cursor.next();
... 
 //  do stuff 
... }

cursor类同样实现了iterator接口,所以你可以使用forEach循环

>   var  cursor  =  db.people.find();
>  cursor.forEach( function (x) {
... print(x.name);
... });
adam
matt
zak

当你调用find方法的时候,shell并不会立刻去查询数据库,直到你真正请求结果的时候才发送查询,这样你可以在实际执行查询之前

追加一些其他的选项,游标的这些方法几乎都是返回游标本身,所以你可以按任意顺序链入这些方法,下边三个查询是等价的

>   var  cursor  =  db.foo.find().sort({ " x "  :  1 }).limit( 1 ).skip( 10 );
>   var  cursor  =  db.foo.find().limit( 1 ).sort({ " x "  :  1 }).skip( 10 );
>   var  cursor  =  db.foo.find().skip( 10 ).limit( 1 ).sort({ " x "  :  1 });

在这个时候查询并未执行,所有的函数都只是构建查询。现在我们调用hasNext方法,

>  cursor.hasNext()

这时候查询被送到服务器,shell就立刻取到了前100条结果或者前4MB的结果,所以接下来在调用next方法的时候就不会再发送请求

以及接受结果,当第一次返回的结果集用完的时候,shell会再次联系服务器,请求更多的结果。

Limits, Skips, 和Sorts

limit函数限制返回的结果集的上限,如,只返回3个结果

>  db.c.find().limit( 3 )

skip函数跳过前x个结果,返回剩余的

>  db.c.find().skip( 3 )

sort方法使用一组键值对做参数,key是document里的key的名字,value是1升序或者-1降序。

如,按名字升序和年龄降序排序

>  db.c.find().sort({username :  1 , age :  - 1 })

比较顺序

mongoDB有一个关于各种数据类型之间比较的等级制度。在某些情况下,你可能有一个key,它的值有多种类型,如果你想按照该

key排序,mongoDB有一个预定义好的顺序,它们从小到大分别为:

        1. Minimum value
        2. null
        3. Numbers (integers, longs, doubles)
        4. Strings
        5. Object/document
        6. Array
        7. Binary data
        8. Object ID
        9. Boolean
        10. Date
        11. Timestamp
        12. Regular expression
        13. Maximum value

获取一致性的结果

处理数据的常见方式就是从mongoDB里取出来,然后修改它,再存储进mongoDB,如下:

 

cursor  =  db.foo.find();

while  (cursor.hasNext()) {
        var  doc  =  cursor.next();
        doc 
 =  process(doc);
        db.foo.save(doc);
}

结果集数量很小的时候,这样子做是没问题的,如果结果集很大,这个做法就行不通了。

想象一下document是如何存储的,你可以像下图4-1一样来理解存储document的collection,每个雪花代表一个document,因为

它们和document一样,都很漂亮而且独一无二。

来源:http://www.open-open.com/lib/view/open1328162238328.html

分享到:
评论

相关推荐

    MongoDB权威指南中文版.pdf

    但根据文件标题《MongoDB权威指南中文版.pdf》和描述内容,我可以推测读者想要了解的是关于MongoDB数据库系统的一些基础知识和概念。 MongoDB是一款流行的开源文档导向数据库系统(NoSQL),它以其高性能、高可用性...

    MongoDB权威指南-中文版.pdf

    通过阅读《MongoDB权威指南》这本书,你可以深入了解MongoDB的原理、安装与配置、数据模型设计、备份与恢复策略、性能调优、安全性等方面的知识,从而更好地运用MongoDB来解决实际问题。无论你是初学者还是经验丰富...

    MongoDB 权威指南.pdf

    ### MongoDB权威指南知识点详解 #### 一、MongoDB概述 MongoDB是一款开源的NoSQL数据库系统,采用BSON(Binary JSON)格式存储文档数据。它支持动态查询、高可用性及横向扩展等特性,适用于大数据量的应用场景。...

    MongoDB权威指南 中文版高清PDF

    《MongoDB权威指南》是一本深入解析该技术的专业书籍,旨在帮助读者全面理解和掌握MongoDB的使用。 本书首先从数据库的基础概念入手,介绍了NoSQL数据库与传统关系型数据库的区别,阐述了MongoDB作为文档数据库的...

    MongoDB权威指南.pdf

    英文版:MongoDB: The Definitive Guide内容简介《MongoDB权威指南》是一本广受好评的MongoDB方面的图书。与传统的关系型数据库不同,MongoDB是一种面向文档的数据库。书中介绍了面向文档的存储方式及利用MongoDB的...

    MongoDB权威指南(中英文两版)

    在数据库管理系统中,索引是提高查询性能的关键,"MongoDB权威指南"也深入探讨了MongoDB的索引类型,如单字段索引、复合索引、地理空间索引等,以及如何根据业务需求创建和优化索引。书中还介绍了聚合框架,这是一个...

    MongoDB权威指南中文版高清版带书签PDF

    在《MongoDB权威指南》这本书中,作者详细地介绍了MongoDB的基础知识、安装配置、数据模型、查询语言、操作管理以及高级特性。以下是对这本书中核心知识点的概述: 1. **MongoDB基础知识**:MongoDB是NoSQL数据库的...

    Mongodb权威指南-最新中文版

    Mongodb权威指南-最新中文版,大小80多M,十分清晰,值得拥有

    MongoDB权威指南 中文版

    ### MongoDB权威指南知识点总结 #### 一、MongoDB概述 - **定义与特点**:MongoDB是一种基于分布式文件存储的数据库系统,属于NoSQL数据库的一种。它将数据以BSON(Binary JSON)格式存储,这种格式类似于JSON文档...

    Mongo DB 权威指南(中文版)

    ### MongoDB权威指南(中文版)知识点总结 #### 一、MongoDB概述 1. **定义与特点**:MongoDB是一款开源的文档型数据库系统,它使用JSON格式的文档存储数据,支持动态模式,使得开发人员可以轻松地进行数据操作。...

    MongoDB权威指南 第二版中文 mobi

    MongoDB权威指南 第二版中文 mobi

    MongoDB权威指南中文版

    《MongoDB权威指南中文版》第1章 简介 第2章 入门 第3章 创建、更新及删除文档 第4章 查询 第5章 索引 第6章 聚合 第7章 进阶指南 第8章 管理 第9章 复制 第10章 分片 第11章 应用举例 附录A 安装MongoDB 附录B ...

    别再用了MongoDB权威指南 中文版

    MongoDB是一种流行的开源、分布式文档型数据库,常用于处理大规模数据。尽管随着MySQL等传统关系型...而《MongoDB权威指南》这样的资源,将帮助读者深入理解MongoDB的原理与实践,以便更好地利用这一强大的数据库技术。

    MongoDB权威指南(中文版)

    《MongoDB权威指南》是一本全面深入探讨MongoDB数据库系统的专著,中文版的发布使得国内用户能够更方便地学习和理解这一强大的NoSQL数据库。MongoDB作为一种分布式文档型数据库,近年来在处理大规模数据存储和高并发...

    MongoDB权威指南(中文版)高清

    856.4.2 例2:网页分类 876.4.3 MongoDB和MapReduce 87第7章 进阶指南 917.1 数据库命令 917.1.1 命令的工作原理 927.1.2 命令参考 937.2 固定集合 957.2.1 属性及用法 967.2.2 创建固定集合 967....

Global site tag (gtag.js) - Google Analytics