MongoDB 学习之查询操作

发布于 2021-11-28 11:40:04 字数 6496 浏览 1050 评论 0

这章我们学习 MongoDB 的查询操作。

Introduction to find

find 方法用于执行 MongoDB 的查询操作。它返回 collecion 中的 documents 子集,没有添加参数的话它将返回整个 collection 数据。

例:查找 c 的所有数据

db.c.find()

find 的第一个参数是查询条件,决定了返回哪些 documents 数据。

例:我们想要查找用户表中年龄为 27 的用户

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

假如我们想要多条件查询怎么办?只要在第一个参数里继续添加条件即可:

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

Specifying Which Keys to Return

有些时候查询你不需要返回所有的键值对。这时你可以在 find 或者 findOne 中的第二个参数里指定你想要返回的。

举个例子,你只要查询 username 和 email,这时可以这样写:

db.users.find({},{"username":1,"email":1})

这时返回:

{
    "_id":ObjectId("4XXXX"),
    "username":"joe",
    "email":"joe@example.com"
}

_id是默认返回的,如果你连它也不需要返回,只需要这样写:

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

Query Conditionals

$lt,$lte,$gt,$gte 用于比较操作,相当于 <,<=,> 和 >=

例如你想要查找年龄在18到30岁之间的用户:

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

$ne 用于不等于操作,例如你想要查询名字不为"joe"的用户,那你可以

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

OR Queries

在MongoDB中OR有两种方法:"$in"和"$or"。

如果你一个单独的key值有超过1种可能的值需要匹配,这时我们会用到"$in"。

假设我们想要查询彩票号码为725或者542或者390的document,我们可以这样

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

$in方法是非常灵活的,它允许你指定的值是不同的类型。

$in的反向操作是$nin,例如我们不想查询彩票号码为 725,542 的 document:

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

那么,如果我们想要查询 ticket_no 为 725 或者 winner 为 true 的 document,应该怎么写呢?

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

再来个复杂点的:

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

聪明如你,一定知道上面的意思啦~

$not

$not 从字面意思来看,我想大家都能猜的出来。注意 它可以应用于所有条件之上。

我们先来看下 $mod,$mod 是用来取被除数的操作,它的第一个参数是除数,第二个是余数。

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

这个操作返回了用户的 id_num 为 1,6,11,16... 的 document。

那么如果我们要求返回的 id_num 为 2,3,4,5,7,8,9,10,12 这些值该怎么办呢?这时候 $not 的作用就凸显出来了,我们只需要这样:

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

$not 在与正则表达式的结合使用中是非常有用的,以后我们会介绍。

Conditional Semantics

假如你看过上一篇介绍的 update modifiers,你会注意到以 $ 为前缀的 key 会在不同的位置。在查询中,$lt 在 document 里面;在更新中,$inc 在 document 外面,一般情况下这句话是对的 :conditionals 是一个 docment 的内部 key,modifiers 是 document 的外部 key。

多个查询条件可以在一个单独的 key 中。举例,你想要查询年龄在20到30之间的用户,你会在 age 这个查询key中用到 $gt 和 $lt:

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

多个 update modifiers 不能被用在同一个 key 上,例如这样是错误的:

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

因为它改变了 age 两次。

还有一些元操作是用在 document 的外部的:$and、$or、$nor

他们都和下面的例子用法相似:

db.users.find({"$and":[{"x":{"$lt":1}},{"x":4}]})

Type-Specific Queries

null

null 比较奇怪,它不仅能匹配自己也能匹配 does not exist(也就是指缺少那个键的),如果在 c 中有这么几条条数据

{"_id":ObjectId("4XXX"),"y":null}
{"_id":ObjectId("4XXX"),"y":1}
{"_id":ObjectId("4XXX"),"y":2}

这时我们输入查询语句:

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

发现返回数据为:

{"_id":ObjectId("4XXX"),"y":null}
{"_id":ObjectId("4XXX"),"y":1}
{"_id":ObjectId("4XXX"),"y":2}

那么我们只想找值为 null,我们可以这样写:

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

Regular Expressions

正则表达式对于字符串匹配是非常有用的。例如我们想要查找用户名为 Joe 或者 joe 的用户:

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

正则表达式也可以匹配自己:

>db.foo.insert({"bar": /baz/})
>db.foo.find({"bar": /baz/})
{
   "_id":ObjectId("4XXX"),
   "bar": /baz/
}

Querying Arrays

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

这时我们可以用 $all 查询包含 apple 和 banana 的数据:

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

查询结果:

db.food.insert({"_id":1,"fruit":["apple","banana","peach"]})
db.food.insert({"_id":3,"fruit":["cherry","banana","apple"]})

我们来看看第二条返回结果,banana 在 apple 前面,而查询条件中的 banana 是在后面,由此我们可以看出数组排序是无关紧要的。

另外,当 $all 中的数组中只有一个元素时,它的用法相当于不使用 $all。

例:{"fruit":{"$all":["apple"]}} 用法等同与 {"fruit":"apple"}

你也可以对数组中的特定索引值进行匹配,例:

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

上面的意思是对 fruit 字段的第 3 个值进行匹配。

$size

$size 是一个很有用的查询条件,它允许你根据数组的长度进行匹配查找。

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

$size 不能结合别的条件一起使用,例如 $gt

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

上面这种用法是错误的。

$slice

在之前的章节我们已经说过 find 的第二个参数用于返回特殊的 key 值。$slice 可以返回数组key值的子集。

 db.food.find({},{"fruit":{"$slice":2}})

返回的值为:

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

另外 $slice 还能做分页

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

上面的 2 代表 skip 2 个元素,总的意思就是取 3-4 的数据。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

等你爱我

暂无简介

0 文章
0 评论
569 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文