现在的位置: 首页 > 综合 > 正文

MongoDB008 查询(一)

2013年12月04日 ⁄ 综合 ⁄ 共 5472字 ⁄ 字号 评论关闭

查询

 

1.      find简介

简单用法

>db.c.find() 等价于 >db.c.find({})

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

>db.users.find({“username” : “joe”,”age” 27})

         指定返回的键

         //查询出所有的文档,只返回文档中key为username和email的键值对,但是_id这个键总是会被返回,不管有没有指定

         >db.users.find({},{“username”: 1,”email” : 1})

         //可以剔除查询结果中的某个键/值对

         >db.users.find({},{“username”: 1,”_id” : 0})

         //简单查询限制 数据库所关心的查询文档的值必须是常量,也就是不能引用文档中其他键的值,如在stock集合中,in_stock和num_sold是两个键,想通过下面的方式查询是不可行的。

         >db.stock.find({“in_stock”: “this.num_sold”})

         这个功能可以使用$where来实现,但是尽可能通过设计优良的文档结构来使用简单查询完成操作,这样性能会比较好。

2.       

2.1   查询条件

“$lt”、“$lte”、“$gt”和“$gte”就是全部的比较操作符,分别对应<、<=、>、>=

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

>start = new Date(“01/01/2007”)

>db.users.find({“registered” : {“$lt” : start}})

 

“$ne” !=

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

2.2 OR查询和IN查询

MongoDB中有两种方式进行OR查询。”$in”可以用来查询一个键的多个值。”$or”更通用一些,用来完成多个键值的任意给定值。

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

“$in”非常灵活,可以指定不同类型的条件和值。

>db.users.find({“user_id” : {“$in” : [12345,”joe”]}})

与”$in”对应的是”$nin”

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

“$or”用法如下:

>db.raffle.find({“$or” : [{“ticket_no” :525},{“winner” :true}]})

“$or”可以含有其他条件句。例如,如果想要将”ticket_no”与那3个值匹配上,外加”winner”键,就可以这么做

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

使用普通的AND型的查询时,总是想尽可能地用最少的条件限定结果的范围(越苛刻的条件越是放在前面),Or型的查询正相反,第一个条件尽可能地匹配更多的文档,这样才是最为有效的。

2.3   $not

“$not”的用法示例:

//查询出id_num对5取模值为1的文档

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

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

         2.4条件句的规则

                   比较更新修改器和查询条件,会发现以$开头的键处在不同的位置。在查询中,”$lt”在内层文档,而更新中”$inc”则是外层文档的键。基本可以指定:条件句是内层文档的键,而修改器则是外层文档的键。可对一个键应用多个条件。例如,要查找年龄为20-30的所有用户,可以在”age”键上使用”$gt”和”$lt”:

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

        一个键可以有多个条件,但是一个键不能对应多个更新修改器。例如,修改器文档不能同时含有{“$inc” : {“age” : 1},”$set” : {age : 20}},因为修改了”age”两次,但是对于查询条件名就没有这种限定。

 

3.      特定于类型的删除

3.1   null

> db.c.find()

{"_id" : ObjectId("51b04490369e7729c62c5c8a"), "y": null }

{"_id" : ObjectId("51b044a5369e7729c62c5c8b"), "y": 1 }

{"_id" : ObjectId("51b044b0369e7729c62c5c8c"), "y": 2 }

> db.c.find({"y" : null})

{"_id" : ObjectId("51b04490369e7729c62c5c8a"), "y": null }

> db.c.find({"z" : null})

{"_id" : ObjectId("51b04490369e7729c62c5c8a"), "y": null }

{"_id" : ObjectId("51b044a5369e7729c62c5c8b"), "y": 1 }

{"_id" : ObjectId("51b044b0369e7729c62c5c8c"), "y": 2 }

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

         3.2正则表达式

                   //忽略大小写,找到名字为joe的用户

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

         3.3查询数组

> db.food.find()

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

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

{ "_id" : ObjectId("51b04bf1369e7729c62c5c8d"),"fruit" : [ "apple", "banana", "

peach" ] }

> db.food.remove()

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

{ "_id" : 1, "fruit" : [ "apple","banana", "peach" ] }

{ "_id" : 3, "fruit" : [ "cherry","banana", "apple" ] }

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

{ "_id" : 1, "fruit" : [ "apple","banana", "peach" ] }

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

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

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

{ "_id" : 1, "fruit" : [ "apple","banana", "peach" ] }

//$size并不能与其他查询子句组合(比如”$gt”)

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

//$slice返回数组的一个子集合

//返回符合条件的文档的comments数组的前10条评论

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

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

//跳过前23个元素,返回第24个-第33个元素

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

//除非特别声明,否则使用”$slice”时将返回文档中的所有键。别的键说明符都是默认不返回未提及的键,这点与”$slice”不太一样。

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

{

        "_id" :ObjectId("51b0583f369e7729c62c5c8e"),

        "title" :"A blog post",

        "content" :"...",

        "comments" :[

                {

                       "name" : "bob",

                       "email" : "bob@example.com"

                }

        ]

}

显然这里除了显示comments元素外,也显示了title,content元素。

         3.4查询内嵌文档

         有两种方法查询内嵌文档:查询整个文档,或者只针对其键/值对进行查询。

         文档示例:

         {

                   “name”: {

                            “first”: “Joe”,

                            “last”: “Schmoe”

                   }

                   “age”: 45

         }

         //查询整个文档

         内嵌文档匹配要求整个文档匹配

         >db.people.find({“name” : {“first” : “Joe”,”last”: “Schmoe”}})

         //针对键值对进行查询

         >db.people.find({“name.first” : “Joe”,”name.last”:”Schmoe”})

         //当文档结构变得更加复杂以后,内嵌文档的匹配就需要些技巧。例如,假设有blog文章若干,要找到由Joe发表的5分以上的评论。blog文章的结构如下例所示

         >db.blog.find(){

                   “content”: “…”,

                   “comments”: [

                            {

                                     “author”: “joe”,

                                     “score”: 3,

                                     “comment”: “nice post”

                            },

                            {

                                     “author”: “mary”,

                                     “score”: 6,

                                     “comment”: “terrible post”

                            }

                   ]

         }

         不能直接用db.blog.find({“comments”:{“author”:”joe”,”score”:{“$gte”:5}}})来查寻。内嵌文档匹配要求整个文档完全匹配,而这不会匹配”comment”键。使用db.blog.find({“comments.author”:”joe”,”comments.score”:{“$gte”:”joe”}})同样也不会达到目的。因为符合author条件的评论和符合score条件的评论可能不是同一条评论。也就是说,会返回刚才显示的那个文档,因为”author”:”joe”在第一条评论中匹配了,”score”:6在第二条评论中匹配了。

         要正确地指定一组条件,而不用指定每个键,要使用”$elemMatch”。这种模糊的命名条件能用来部分指定匹配数组中的单个内嵌文档的限定条件。所以正确的写法应该是这样的

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

抱歉!评论已关闭.