第7章 MongoDB的高级语法
MongoDB除了有简单的按键值查询外,还有不少高级查询方式,可以实现更加强大的数据查询功能。MongoDB的聚合查询功能,还能在查询的同时对数据进行处理,从而大大提高数据的处理效率。
7.1 AND和OR操作
在实际情况中,查询条件往往不止一条,这些条件可能需要同时满足,也可能需要从多个条件中任选其一。此时,就需要联合多个查询条件。
7.1.1 实例13:查询同时符合两个条件的人(AND操作)
在使用MongoDB查询时,对同一条记录常常会有多个判断逻辑。
实例描述
假设,数据集example_data_1如图7-1所示。
在这个数据集中,每一行表示一个人的信息,包括年龄(age)、工资(salary)和性别(sex),“id”不重复。
(1)使用隐式操作查询同时满足两个条件(age大于20,sex为“男”)的数据。
(2)使用显式AND操作查询所有年龄大于20且性别为“男”的数据。
(3)混合使用显式AND操作与隐式AND操作查询所有年龄大于20,性别为“男”,并且id小于10的数据。
图7-1 数据集example_data_1
1.隐式AND操作
现在要查询所有age大于20并且sex为“男”的数据。
可以构造以下这样一个查询语句:
对age与sex这两个字段的查询条件需要同时满足。
“同时满足”在逻辑上叫作“与(AND)”。
对于查询语句:
没有出现AND这个关键字,却能表达出“与”的关系,因此称为“隐式AND操作(implicit AND operation)”。
2.显式AND操作
MongoDB也有“显式AND操作(explicit AND operation)”。
显式AND操作的语法为:
本质上,这种写法和基础部分的查询条件是一致的,只不过基础部分的Key是各个字段名,而这里的Key是“$and”这样一个关键字,并且Value是一个列表,而列表中是很多个字典。每一个字典的写法和基础部分的“find”对应的第1个参数完全相同。
例如,查询所有年龄大于20且性别为“男”的数据。
使用显式AND操作的写法为:
显式AND操作的运行效果如图7-2所示。返回结果和隐式AND操作完全一致。
图7-2 使用显式AND操作
提示:
随着查询的条件越来越复杂,MongoDB查询语句中的括号会越来越多,因此要养成先把括号闭合,再填写里面内容的习惯。这样才不容易漏掉括号的后半部分,也不会把大括号中括号小括号的后半部分顺序搞错。
例如:
db.getCollection('example_data_1').find({'$and': [{'age': {'$gt': 20}}, {'sex': ’男’}]})
应这样写:
(1)写db.getCollection('example_data_1').find())。
(2)用键盘方向键移动光标到find括号的中间,把大括号的左右部分写完。
(3)用键盘方向键将光标移动到大括号中间,写’$and': []。
(4)用键盘方向键把光标移动到中括号里,写具体的每一个查询表达式。
3.显式AND操作和隐式AND操作混用
显式AND操作和隐式AND操作可以混合使用。
例如,查询所有年龄大于20,性别为“男”,并且id小于10的数据。
可以混合使用显式AND操作与隐式AND操作。具体代码如下:
查询结果如图7-3所示。
图7-3 混合使用显式AND操作与隐式AND操作
虽然MongoDB可以混合使用显式AND操作与隐式AND操作,但明显直接写为隐式AND操作会更简单易懂。
所有隐式AND操作都可以改写为显式AND操作。但反之不行,有一些显式AND操作不能改写为隐式AND操作。具体例子见7.1.2中的2.小标题。
7.1.2 实例14:查询只符合其中任一条件的人(OR操作)
实例描述
对于example_data_1数据集:
(1)查找所有年龄(age)大于28岁的数据,或者工资(salary)大于9900的数据。
(2)查询同时满足以下两个要求的数据:
● age大于28,或者salary大于9900。
● sex为“男”,或者id小于20。
(3)使用一条语句查询符合下面四种情况的所有数据:
● age大于28的男性。
● age大于28且id小于20的女性。
● salary大于9900的男性。
● salary大于9900且id小于20的女性。
在某些时候,多个查询条件只需要满足一个就可以了。这种情况有两种处理方式:
● 按照优先级依次把每一个查询条件带入到 MongoDB 中执行,如果有结果就使用结果,如果没有结果就换下一个查询条件。
● 使用“或(OR)”操作。
1.显式OR操作举例
OR操作与显式AND操作的格式完全一样,只需要把关键字“$and”换成“$or”即可。
具体语法如下:
collection.find({'$or': [字典1, 字典2, 字典3, ……, 字典n]})
OR操作会自动按顺序去检查每一个条件,直到某一个查询条件找到至少一条数据为止。
查询语句可以写为:
查询结果如图7-4所示。
图7-4 age大于28或者salary大于9900
从图7-4可以看出,对于每一行数据:
● 如果age大于28,那么salary的值是多少都无所谓。
● 如果age小于等于28,那么必有salary大于9900。
MongoDB在执行OR操作时会遵循一个“短路原则”:只要前面的条件满足了,那后面的条件就直接跳过。
如果age大于28,那就不需要去检查salary的值是多少。只有在age不满足查询条件时,才会去检查salary的值。
提示:
OR操作一定是显式的,不存在隐式的OR操作。
2.不能写成隐式的AND操作的举例
在7.1.1小节的最后提到,某些显式的AND操作不能写成隐式的AND操作,这里举一个例子。
这个查询其实是一个AND操作内部套两个OR操作。
查询语句见代码7-1。
代码7-1 不能写成隐式AND操作的例子
查询结果如图7-5所示。
图7-5 一个AND操作内部包含多个OR操作
对于这种查询条件,是没有办法写成隐式AND操作的。
提示:
对于复杂的查询条件,使用换行和缩进可以让代码看起来更清晰易懂。
7.1.3 实例15:用Python实现MongoDB的AND与OR操作
实例描述
使用Python操作MongoDB,查询数据集example_data_1的数据,只查询一次就找到符合下面四种情况的所有数据:
(1)age大于28的男性。
(2)age大于28并且id小于20的女性。
(3)salary大于9900的男性。
(4)salary大于9900且id小于20的女性。
Python中的显式AND操作与OR操作写法,与MongoDB中的写法完全一样。
下面用Python来实现7.1.2小节中的一个AND操作套两个OR操作。代码如下:
代码7-2 在Python中实现显式AND操作与OR操作
查询结果如图7-6所示。
图7-6 显式AND操作与OR操作在Python中的写法