数据准备

在学习文档查询之前,先录入以下数据:

> 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可识别的对象,所以查询时会非常慢。