查询
# find简介
查询所有的文档可以使用下面的命令
db.test.find({})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"like" : []
}
2
3
4
5
6
7
如果想查询特定内容,比如name为小游的文档
db.test.find({"name":"小游"})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"like" : []
}
2
3
4
5
6
7
# 返回指定的键
如果我们只需要name字段,我们可以这样,默认_id会返回,我们可以置为0,避免返回
db.test.find({},{"name":1,"_id":0})
/* 1 */
{
"name" : "小游"
}
2
3
4
5
# 限制
查询文档的值必须是常量,也就是不能引用文档中其他键的值。
# 查询条件
# 查询条件
db.test.find({"age":{"$gte":18,"$lte":30}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : []
}
2
3
4
5
6
7
8
# OR查询
我们可以使用 "$in"
来查询一个键的多个值。也可以使用 "$OR"
一般来说OR会通用一些。
db.test.find({"age":{"$in":[20,100]}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : []
}
/* 2 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : "张三",
"age" : 100,
"like" : []
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
与 $in
相对的是 $nin
,会返回不匹配的文档。但是这个只能查询单个条件,下面我们来使用 or 查询年龄在20或者名字为张三的人
db.test.find({"$or":[{"age":{"$in":[20]}},{"name":"张三"}]})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : []
}
/* 2 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : "张三",
"age" : 100,
"like" : []
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# $NOT
这个是原语句,可以用在其他任何条件上
db.test.find({"age":{"$not":{"$in":[20]}}})
/* 1 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : "张三",
"age" : 100,
"like" : []
}
2
3
4
5
6
7
8
# 条件句的规则
条件句是内层文档的键,修改器是外层文档的键
# 内层文档
db.test.find({"age":{"$not":{"$in":[20]}}})
# 外层文档
db.test.update({"name":"小游"},{"$set":{"age":0}})
2
3
4
# 特定类型的查询
# null
# 正则表达式
查询条件可以直接设置为正则表达式,用于灵活有效的匹配字符串
db.test.find({"name":/小/i})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : []
}
2
3
4
5
6
7
8
# 查询数组
db.test.find({"like":"看番"})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
如果想匹配多个数组,可以使用 $all
来进行匹配,里面的内容是没有顺序的
db.test.find({"like": {"$all":["写代码","看番"]}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
# 下面这个语句匹配不到内容
db.test.find({"like": {"$all":["写代码","看番","玩"]}})
2
3
4
5
6
7
8
9
10
11
12
13
如果想查询指定长度的数组,可以使用 $size
db.test.find({"like": {"$size":2}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
如果只想返回数组的前一个元素,可以使用 $slice
操作符,当然也可以知道偏移值
db.test.find({"name":"小游"},{"like":{"$slice":1}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码"
]
}
# 使用偏移值,跳过前一个元素,返回一个元素
db.test.find({"name":"小游"},{"like":{"$slice":[1,1]}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查询内嵌文档
db.test.find({"name.first":"小"})
/* 1 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : {
"first" : "小",
"last" : "游"
},
"age" : 100,
"like" : []
}
2
3
4
5
6
7
8
9
10
11
# $where查询
where查询可以执行任意JavaScript语句作为查询的一部分。如果return为真,就返回这条数据,否则就不返回
db.test.find({"$where":function(){
return this.name === "小游"
}})
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
当然我们也可以使用一个字符串来指定where查询
db.test.find({"$where":"this.name === '小游'"})
# 游标
数据库会使用游标来返回find的执行结果,我们可以对这个cursor对象进行遍历操作
var cursor=db.test.find({})
cursor.forEach(function(x){
print(x.name)
})
小游
张三
# 也可以这样进行操作,返回的记过都是一样的
var cursor=db.test.find({})
while(cursor.hasNext()){
print(cursor.next().name);
}
2
3
4
5
6
7
8
9
10
11
# limit,skip,sort
最常用的查询选项就是限制返回结果的数量,忽略一定数量的结果并排序。所有这些选项一定要在查询被派发到服务器之前添加,比如我们只想返回一个结果
db.getCollection('test').find({}).limit(1)
/* 1 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
skip
可以跳过文档,比如我们跳过第一个文档
db.getCollection('test').find({}).skip(1)
/* 1 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : "张三",
"age" : 100,
"like" : []
}
2
3
4
5
6
7
8
sort
可以设置排序,1为升序,-1为降序
db.getCollection('test').find({}).sort({_id:-1})
/* 1 */
{
"_id" : ObjectId("609cd4df71a920015b3da7ac"),
"name" : "张三",
"age" : 100,
"like" : []
}
/* 2 */
{
"_id" : ObjectId("609bb9f16ac4daf1370a10c6"),
"name" : "小游",
"age" : 20,
"like" : [
"写代码",
"看番"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如果一个键有多个值,那么MongoDB的比较顺序如下
(1)最小值 2)nu11 (3)数字(整型、长整型、双精度) 4)字符串 (5)对象/文档 (6)数组 (7)二进制数据 (8)对象ID (9)布尔型 (10)日期型 (11)时间戳 (12)正则表达式 (13)最大值
# 避免使用SKIP略过大量结果
用skip略过少量的文档还是不错的。但是要是数量非常多的话,skip就会变得很慢(几乎每个数据库都有这个问题,不仅仅是 MongoDB),所以要尽量避免。通常可以向文档本身内置查询条件,来避免过大的skip,或者利用上次的结果来计算下一次查询。
不用skip对结果分页
通常情况下我们会使用skip对结果进行分页,比如下面这个
我们也可以使用下面这种方式来进行分页
我们只需要记住一个时间点,然后找出比这个时间点大的,在使用limit进行分页操作。
随机选取文档
如果想随机选取文档,我们其实可以在文档里面加一个字段,然后在查询,这样就可以实现随机文档的效果了
# 高级查询选项
查询分类包装查询和普通查询两种
// 普通查询
var cursor=db.foo.find({"foo :"bar"})
// 包装查询
var cursor db.foo.find({"foo":"bar"}). sort({"x":1})
2
3
4
实际情况不是将{"foo":"bar"}作为查询直接发送给数据库,而是将查询包装在一个更大的文档中。shell会把查询从{"foo":"bar"}转换成{"$query":{"fool":"bar"},"$orderby" :{"x":1}}
# 获取一致结果
数据处理通常的一种做法就是先把数据从 MongoDB中取出来,然后经过某种变换最后再存回去,结果少的话还好,但是一旦结果一多,因为之前的空间是固定的,我们修改文档后,空间比原来的大,这个时候MongoDB就会移动文档,找出游标返回的数据不一致的问题
应对这个问题的方法就是对查询进行快照。如果使用了“$snapshot”选项,查询就是针对不变的集合视图运行的。所有返回一组结果的查询实际上都进行了快照。不一致只在游标等待结果时集合内容被改变的情况下发生。
# 游标内幕
← 文档创建、更新、删除 索引→