3.1 查询操作符操作符就是对数据进行操作的符号,其表达了要对数据执行的操作。数据库系统的每一条查询指令都有一个操作符,表示该指令应该执行什么性质的操作。
条件操作符最常用也是最简单的操作符<、<=、>、>=如下面的代码所示: //field 大于 value db.collection.find({"field":{$gt:value}}); //field 小于 value db.collection.find({"field":{$lt:value}}); //field 大于等于 value db.collection.find({"field":{$gte:value}}); //field 小于等于 value db.collection.find({"field":{$lte:value}}); 如果要同时满足多个条件,可以如下面的代码所示: //value1 < field < value2 db.collection.find({"field":{$gt:value1,$lt:value2}}); $all匹配所有此操作符跟SQL语法的in类似,不同的是in只需要匹配括号内的某一个值,而$all必须满足括号内的所有值,如下面的代码所示: db.users.find({age:{$all:[6, 8]}}); 上例可以查询出以下文档: {name: 'David', age: 26, age: [ 6, 8, 9 ] } 但查询不出以下这条文档: {name: 'David', age: 26, age: [ 6, 7, 9 ] } $exists判断字段是否存在 此操作符用于判断某个字段是否存在,例如查询所有存在age字段的记录,如下面的代码所示: db.users.find({age: {$exists: true}}); 查询所有不存在name字段的记录,如下面的代码所示: db.users.find({name: {$exists: false}}); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find(); { "_id" : ObjectId("4fb4a773afa87dc1bed9432d"), "age" : 20, "length" : 30 } { "_id" : ObjectId("4fb4a7e1afa87dc1bed9432e"), "age_1" : 20, "length_1" : 30 } 查询存在字段age的数据,如下面的代码所示: > db.c1.find({age:{$exists:true}}); { "_id" : ObjectId("4fb4a773afa87dc1bed9432d"), "age" : 20, "length" : 30 }通过实验结果可以看出只显示了age字段的数据,age_1的数据并没有显示出来。
null值处理此操作符用于处理null值,null值的处理稍微复杂,如下面的代码所示: > db.c2.find() { "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null } { "_id" : ObjectId("4fc34be01d8a39f01cc17ef5"), "name" : "Jacky", "age" : 23 } { "_id" : ObjectId("4fc34c1e1d8a39f01cc17ef6"), "name" : "Tom", "addr" : 23 } 其中,“Lily”的age字段为空,“Tom”没有age字段,想找到age为空的行如下面的代码所示: > db.c2.find({age:null}) { "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null } { "_id" : ObjectId("4fc34c1e1d8a39f01cc17ef6"), "name" : "Tom", "addr" : 23 } 奇怪的是,我们以为只能找到“Lily”,但“Tom”也被找出来了,所以“null”不仅能找到它自身,也能找到不存在age字段的记录。那么怎么样才能只找到“Lily”呢?用exists来限制一下即可,如下面的代码所示: > db.c2.find({age:{"$in":[null], "$exists":true}}) { "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null }跟期望的结果一样,只有“Lily”被找出来了。
$mod取模运算此操作符用于取模运算。例如查询age取模10等于1的数据,如下面的代码所示: db.student.find( { age: { $mod : [ 10 , 1 ] } } ) 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 } { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 } { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 } 查询age取模6等于1的数据,如下面的代码所示: > db.c1.find({age: {$mod : [ 6 , 1 ] } }) { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }可以看出,只显示age取模6等于1的数据,其他不符合规则的数据并没有显示出来。
$ne不等于此操作符用于布尔不等于的运算。例如查询x的值不等于3的数据,如下面的代码所示: db.things.find( { x : { $ne : 3 } } ); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 } { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 } { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 } 查询age的值不等于7的数据,如下面的代码所示: > db.c1.find( { age : { $ne : 7 } } ) { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 } { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }可以看出,只显示age不等于7的数据,age等于7的数据没有显示出来。
$in包含此操作符与SQL标准语法的用途一样,即要查询的数据在一个特定的取值范围内。例如,查询x的值在2、4、6范围内的数据,如下面的代码所示:
db.things.find({x:{$in: [2,4,6]}}); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 } { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 } { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 } 查询age的值在7、8范围内的数据,如下面的代码所示: > db.c1.find({age:{$in: [7,8]}}) { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 } { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }可以看出只显示age等于7或8的数据,其他不符合规则的数据并没有显示出来。
$nin不包含此操作符与SQL标准语法的用途是一样的,即要查询的数据在一系列枚举值的范围外。查询x的值在2、4、6范围外的数据,如下面的代码所示:
db.things.find({x:{$nin: [2,4,6]}}); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 } { "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 } { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 } 查询age的值在7、8范围外的数据,如下面的代码所示: > db.c1.find({age:{$nin: [7,8]}}) { "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }通过结果可以看出只显示age不等于7或8的数据,其他不符合规则的数据并没有显示出来。
$size匹配数组元素个数此操作符用于统计数组中的元素个数。例如,对于记录: {name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] } 它匹配以下查询: db.users.find({favorite_number: {$size: 3}}) 但不匹配以下查询: db.users.find({favorite_number: {$size: 2}}) 10. count查询记录条数 此操作符用于统计记录的条数。如下面的代码所示: db.users.find().count(); 以下返回的不是5,而是user表中所有记录的数量,如下面的代码所示: db.users.find().skip(10).limit(5).count(); 如果要返回限制之后的记录数量,要使用count(true)或者count(非0) ,如下面的代码所示: db.users.find().skip(10).limit(5).count(true); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 } { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 } 查询c1表的数据量,如下面的代码所示: > db.c1.count() 2通过结果可以看出,表中共有2条数据。
skip限制返回记录的起点此操作符用于过滤结果集中的某些行。例如,从第3条记录开始,返回5条记录 ,如下面的代码所示: db.users.find().skip(3).limit(5); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 } { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 } 查询c1表的第2条数据,如下面的代码所示: > db.c1.find().skip(1).limit(1) { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }通过结果可以看出,表中第2条数据被显示了出来。
sort排序此操作符用于将结果集排序。例如,以年龄升序(asc)排列,如下面的代码所示: db.users.find().sort({age: 1}); 以年龄降序(desc)排列,如下面的代码所示: db.users.find().sort({age: -1}); 接下来举一个实际的例子,c1表的数据如下面的代码所示: > db.c1.find() { "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 } { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 } 查询c1表按age升序排列,如下面的代码所示: > db.c1.find().sort({age: 1}) { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 } { "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 } 通过结果可看到第1条是age=10的,而后按升序排列结果集。 查询c1表按age降序排列,如下面的代码所示: > db.c1.find().sort({age: -1}) { "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 } { "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }通过结果可看到第1条是age=20的,而后按降序排列结果集。
distinct去掉重复值在表中可能会包含重复值,distinct操作符用来过滤掉多余的重复记录, 对于重复记录只保留一条。通常用它来返回不重复记录的条数,如下面的代码所示: > db.t2.find() { "_id" : ObjectId("4e023565b42bc90ec25b7c07"), "name" : "Tom", "age" : 20 } { "_id" : ObjectId("4e023565b42bc90ec25b7c08"), "name" : "Jerry", "age" : 20 } { "_id" : ObjectId("4e023566b42bc90ec25b7c09"), "name" : "Rose", "age" : 18 } > > db.t2.distinct("name") [ "Tom", "Jerry", "Rose" ] > > db.t2.distinct("age") [ 20, 18 ] >name的不重复值为3个,age的不重复值为2个,调用distinct操作符后,返回一个列表,里面包含了不重复值的枚举值。注意 这种操作在数据量较大的表里会比较耗时,请慎重使用这个功能。
group分组统计by子句主要用于对where中得到的结果进行分组。也就是说,它在where子句之后执行,对经过where筛选后的结果按照某些列进行分组,之后进行相应的处理工作。当使用聚集函数的时候,除非对整个语句的查询结果集进行聚集运算,否则都要通过指定group by子句来确定是对某类结果集进行聚集运算,如下面的传统SQL代码所示:
select a,b,sum(c) csum from coll where active=1 group by a,b上面的语句用MongoDB也是可以实现的,如下面的代码所示:
db.coll.group( {key: { a:true, b:true }, cond: { active:1 }, reduce: function(obj,prev) { prev.csum += obj.c; }, initial: { csum: 0 } });参数说明:1)key:要分组的列。本例中为a和b。2)cond:分组条件。可以理解为where条件内容,本例中为active=1。3)reduce: 分组计算的方法。本例中为sum(c)。4)initial:分组计算的初始值。本例中指csum的值从0开始计算。