MongoDB 学习之查询操作
这章我们学习 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 技术交流群。
上一篇: 前端开发学习之基本语法
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论