DBA MongoDB 文档查询
数据准备
在学习文档查询之前,先录入以下数据:
> db.collection.drop()
> db.collection.insertMany(
[
{
_id:1,
name:"Jack",
gender:"male",
age:18,
grades:
{
Js:88,
Py:92,
Go:78
},
class:{
name:"三年级一班",
numPeople:30,
}
},
{
_id:2,
name:"Tom",
gender:"male",
age:19,
grades:{
Js:72,
Py:81,
Go:56,
},
class:{
name:"三年级一班",
numPeople:30,
}
},
{
_id:3,
name:"Ken",
gender:"male",
age:20,
grades:{
Js:61,
Py:72,
Go:96,
},
class:{
name:"三年级一班",
numPeople:30,
}
},
{
_id:4,
name:"Keisha",
gender:"female",
age:17,
grades:{
Js:31,
Py:42,
Go:26,
},
class:{
name:"三年级二班",
numPeople:21,
}
},
{
_id:5,
name:"Kelly",
gender:"female",
age:18,
grades:{
Js:71,
Py:64,
Go:19,
},
class:{
name:"三年级二班",
numPeople:21,
}
}
]
)
基础查询
查询与格式化
下面是对集合查询文档的基础命令:
命令 | 描述 |
---|---|
db.集合名.find(query) | 查询符合条件的所有文档,如不指定查询条件则返回全部文档 |
db.集合名.findOne(query) | 查询符合条件的所有文档,如不指定查询条件则返回一条文档 |
pretty() | 对查询结果进行标准的JSON格式化显示 |
使用find()方法可以查出一个集合下所有的文档,或者指定条件查询特定的文档:
> db.collection.find()
> db.collection.find({"name" : "Jack"})
使用.pretty()方法可以对查询结果进行标准的JSON格式化:
> db.collection.find().pretty()
指定查询键
如果想查询指定的键,只获取某一字段与值,则可以对find()函数的第二参数进行填写,第二参数默认为{}。
示例如下:
> db.collection.find({"name" : "Jack"}, {"grades" : 1})
{ "_id" : 1, "grades" : { "Js" : 88, "Py" : 92, "Go" : 78 } }
如果想隐藏掉_id字段,则可以通过第二参数中_id对应0来隐藏:
> db.collection.find({"name" : "Jack"}, {"grades" : 1, "_id" : 0})
{ "grades" : { "Js" : 88, "Py" : 92, "Go" : 78 } }
大小与个数
下面是查询集合中文档个数与集合大小的命令:
命令 | 描述 |
---|---|
db.集合名.count() | 返回集合中文档个数 |
db.集合名.totalSize() | 统计集合下所有文档的大小,规则为集合索引信息+数据压缩存储后的大小 |
示例演示如下:
> db.collection.count()
5
> db.collection.totalSize()
40960
查询子文档
层级关系可以用.点符号来进行查询,如下示例,我想查询Jack同学的Js成绩:
> db.collection.find({"name" : "Jack"}, {"grades.Js" : 1, "_id" : 0})
{ "grades" : { "Js" : 88 } }
显示结果
limit()方法可跟在查询之后,用于显示指定的条目:
> db.collection.find().pretty().limit(2)
skip()方法可跟在limit()方法之后,用于指定显示第几条数据,从0开始即使:
> db.collection.find().pretty().limit(2).skip(1) # 显示第二条数据
sort()方法可跟在查询或者显示结果的方法之后,指定特定字段对显示结果进行排序,1为升序,-1为降序:
> db.collection.find({},{"age" : 1, "_id" : 0}).sort({"age" : 1})
修改器查询
等值查询
MongoDB中在find()或者findOne()里可指定的等值查询语法如下:
条件语法 | 描述 |
---|---|
等值查询 | |
{ k : { $eq : v } } | 同上,等值查询 |
示例,查询年龄是18的文档,拿名字以及年龄:
> db.collection.find({"age" : 18}, {"_id" : 0, "name": 1, "age" : 1})
{ "name" : "Jack", "age" : 18 }
{ "name" : "Kelly", "age" : 18 }
> db.collection.find({"age" : {$eq : 18}}, {"_id" : 0, "name": 1, "age" : 1})
{ "name" : "Jack", "age" : 18 }
{ "name" : "Kelly", "age" : 18 }
比较查询
MongoDB中在find()或者findOne()里可指定的比较查询语法如下:
条件语法 | 描述 |
---|---|
{ k : { $lt : v } } | 小于查询 |
{ k : { $lte : v } } | 小于或等于 |
{ k : { $gt : v } } | 大于查询 |
{ k : { $gte : v } } | 大于或等于 |
{ k : { $ne : v } } | 不等于 |
示例,查询年龄大于19岁的文档,拿名字以及年龄:
> db.collection.find({"age" : {$gt : 19}}, {"_id" : 0, "name": 1, "age" : 1})
{ "name" : "Ken", "age" : 20 }
示例,查询Js成绩小于80的文档,拿名字以及Js成绩:
> db.collection.find({"grades.Js" : {$lt : 80}}, {"_id" : 0, "name": 1, "grades.Js" : 1})
{ "name" : "Tom", "grades" : { "Js" : 72 } }
{ "name" : "Ken", "grades" : { "Js" : 61 } }
{ "name" : "Keisha", "grades" : { "Js" : 31 } }
{ "name" : "Kelly", "grades" : { "Js" : 71 } }
包含查询
MongoDB中在find()或者findOne()里可指定的包含查询语法如下:
条件语法 | 描述 |
---|---|
{ k : { $in : [ v1, v2, … ] } } | 包含查询,如果数组中v只有1个,则为等值查询 |
{ k : { $nin : [ v1, v2, … ] } } | 不包含查询 |
示例,查询年龄在18,19,20岁的文档,拿名字以及年龄:
> db.collection.find({"age" : {$in : [18, 19, 20]}}, {"_id" : 0, "name": 1, "age" : 1})
{ "name" : "Jack", "age" : 18 }
{ "name" : "Tom", "age" : 19 }
{ "name" : "Ken", "age" : 20 }
{ "name" : "Kelly", "age" : 18 }
逻辑查询
MongoDB中在find()或者findOne()里可指定的逻辑查询语法如下:
条件语法 | 描述 |
---|---|
AND条件 | |
同上,AND条件 | |
OR条件 | |
{ k : { $not : {条件 : v } } } | NOT条件,仅支持对单个k的条件 |
NOT条件,可支持对多个k的条件 |
示例$and,查询Js成绩大于80,并且年龄小于22的文档,拿名字以及Js成绩:
> db.collection.find({"grades.Js" : {$gt : 80}, "age" : {$lt : 22}}, {"_id" : 0, "name" : 1, "grades.Js" : 1})
{ "name" : "Jack", "grades" : { "Js" : 88 } }
> db.collection.find(
{
$and:[
{"grades.Js" : {$gt : 80}},
{"age" : {$lt : 22}}
]
},
{
"_id" : 0,
"name" : 1,
"grades.Js" : 1
}
)
{ "name" : "Jack", "grades" : { "Js" : 88 } }
示例$or,查询年龄是17岁或者Js成绩大于80的文档,拿名字,年龄以及Js成绩:
> db.collection.find(
{
$or:[
{"grades.Js" : {$gt : 80}},
{"age" : {$eq : 17}}
]
},
{
"_id" : 0,
"name" : 1,
"age" : 1,
"grades.Js" : 1
}
)
{ "name" : "Jack", "age" : 18, "grades" : { "Js" : 88 } }
{ "name" : "Keisha", "age" : 17, "grades" : { "Js" : 31 } }
示例$not,查询性别不是male的文档,拿名字和性别:
> db.collection.find(
{
"gender" : {$not : {$eq : "male"}}
},
{
"_id" : 0,
"name" : 1,
"gender" : 1,
}
)
{ "name" : "Keisha", "gender" : "female" }
{ "name" : "Kelly", "gender" : "female" }
示例$nor,查询性别不是male,名字不是kelly的文档:
> db.collection.find(
{
$nor : [
{"gender" : "male"},
{"name" : "Kelly"}
]
},
{
"_id" : 0,
"name" : 1,
"age" : 1,
}
)
{ "name" : "Keisha", "age" : 17 }
存在与类型
MongoDB中在find()或者findOne()里可指定的存在与类型查询语法如下:
语法格式 | 描述 |
---|---|
查询v为null的k,或者没有这个k的文档 | |
{ k : { $exists : bool }} | 查询存在或不存在该k的文档 |
{ k : { $type: “type” }} | 查询该k的v为指定类型的文档 |
示例,null,查询不存在school键的文档,仅展示一个:
> db.collection.findOne({"school" : null})
> db.collection.findOne({"school" : {$exists : false}})
示例,查询name为string类型的文档,仅展示一个:
> db.collection.findOne({"name" : {$type : "string"}})
在查询类型时,你也可以使用数字编号进行代替:
> db.collection.findOne({"name" : {$type : 2}})
$type的数字编号如下表所示:
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1 . |
Max key | 127 |
取余与正则
MongoDB中在find()或者findOne()里可指定的取余与正则查询语法如下:
语法格式 | 描述 |
---|---|
{ k : { $mod : [ 除数, 余数 ] } } | 查询k的v是取余结果值的文档 |
{ k :{ $regex : /表达式/ } } | 查询k的v是被正则表达式所匹配的文档 |
示例,查询age的值是除2余0的文档:
> db.c1.find({"age":{$mod:[2,0]}}); # 18,20年龄的都会查出来
示例,查询key的值被正则表达式所匹配的文档:
> db.c1.find({"name":{$regex:/^J.{2}k$/}});
数组的条件
MongoDB中在find()或者findOne()里可指定的数组的条件查询语法与获取语法如下:
语法格式 | 描述 |
---|---|
{ k : { $all : [ v1, v2, … ] } } | 匹配所有k为数组类型,且k的元素均在查询条件中的文档 |
{ k : { $elemMatch : { k : v } } | 匹配所有k为数组类型,且k的元素均在查询条件范围中的文档,需要配合其他修改器 |
{ k : { $size : int } } | 匹配所有k为数组类型,且k的长度与查询条件设定长度一致的文档 |
{ k : { $slice : [ start, stop ] || int } } | 匹配所有k为数组类型的文档,返回数组中的元素,可进行切片或取一个的操作,位置在指定第二参数(元素获取语法) |
先创建一个集合:
> db.array.drop()
> db.array.insertMany([{"k" : [1, 2, 3, 4, 5]}, {"k" : [1, 2, 3, 4, 5, 6]}])
示例,$all,匹配规则,必须包含1,2,3,4,5,多一个不行,少一个也不行:
> db.array.find({"k" : {$all : [1, 2, 3, 4, 5]}})
示例,$elemMatch,匹配规则,包含1,2,3即可:
> db.array.find({"k" : {$elemMatch : {$in:[1, 2, 3]}}})
示例,$size,返回长度为5的数组:
> db.array.find({"k" : {$size : 5}})
示例,$slice,从第一个开始,向后取3个:
> db.array.find({"k" : {$type : "array"}}, {"k" : {$slice : [1, 3]}})
{ "_id" : ObjectId("6048e85d6be9382bc8346b60"), "k" : [ 2, 3, 4 ] }
{ "_id" : ObjectId("6048e85d6be9382bc8346b61"), "k" : [ 2, 3, 4 ] }
$where查询
最强大的一种查询,能够查询到任意的你想查询的信息,但是查询时不会走索引,所以尽量少用。
它其实是书写一个JavaScript函数进行查询,如下所示,查询所有成绩大于200分的文档:
db.collection.find({
$where: function (){
if (this.grades.Js + this.grades.Go + this.grades.Py > 200){
return true
}
return false
}
})
# return false,不返回文档
# return true,返回文档
# 每次的this都是新的文档
$where本身会将BSON文档转换为JavaScript可识别的对象,所以查询时会非常慢。