1、聚合查询
聚合查询主要使用聚合框架对集合中的文档进行变换与组合,以实现对文档的一连串处理。这些处理包含筛选(Filtering)、投射(projecting)、分组(grouping)、排序(sorting)、限制(limiting)和跳过(skipping)。
聚合操作通过管道操作符进行处理,每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作符。不同的管道操作符可以按任意顺序组合在一起,而且可以被重复任意多次。
1.1、$match
$match用于对文档集合进行筛选,之后就可以在筛选的带的文档子集上做聚合。$match可以使用常规的查询操作符,如$gt/$lt/$in等,但不能在$match中使用地理位置空间操作符。
通常在使用中应尽可能将$match放在管道的前面位置。这样好处为:一是可以快速将不需要的文档过滤掉,以减少管道的工作量;二是如果在投射和分组之前执行$match,查询可以使用索引。
使用示例:
> db.city.aggregate({"$match":{"code":{$lt:2}}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "name" : "北京", "country" : "中国", "code" : 1, "captial" : true, "people" : 20009000, "district" : [ "朝阳1", "通州", "海淀", "大兴" ], "north" : true, "subId" : [ 1, 10, 20, 50, 100 ] }
>
1.2、$project
$project可以从文档中提取字段,可以重命名字段,还可以在这些字段上进行一些操作。$project最简单的操作是选择想要的字段,可以指定包含或不包含某个字段。同时,也可将投射过的字段进行重命名。$fieldName在聚合框架中的含义是引用某个字段的值。
1.2.1、管道表达式
最简单的$project表达式是包含和排除字段,以及字段名称。也可以使用表达式将多个字面量和变量组合在一个值中使用。文档的id默认是包含的。
使用示例:
> db.city.aggregate({"$project":{"name":1,"code":1}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "name" : "北京", "code" : 1 }
{ "_id" : ObjectId("5de5ac646bba334fecac2f30"), "name" : "广州", "code" : 3 }
{ "_id" : ObjectId("5de647f5b4cd9b14f46e0e30"), "name" : "上海", "code" : 2 }
>
1.2.2、数学表达式
数学表达式可用于操作数值。指定一组数值,就可以使用数学表达式进行操作了。
操作语法如下:
- "$add":[ expr1 [ , expr2, … , exprN ] ]。这个操作符接受一个或多个表达式作为参数,将这些表达式相加。
- "$subtract":[ expr1, expr2 ]。接受两个表达式作为参数,用第一个表达式减去第二个表达式作为结果。
- "$multiply":[ expr1 [ , expr2, … , exprN ] ]。接受一个或多个表达式,并将它们相乘。
- "$divide":[ expr1, expr2 ]。接受两个表达式,用第一个表达式除以第二个表达式的商作为结果。
- "$mod":[ expr1, expr2 ]。接受两个表达式作为,将第一个表达式作为除以第二个表达式得到的余数作为结果。
使用示例:
> db.city.aggregate({"$project":{"code+2":{"$add":["$code",2]},"code*2*2*2":{"$multiply":["$code",2,2,2]},"code%3":{"$mod":["$code",3]}}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "code+2" : 3, "code*2*2*2" : 8, "code%3" : 1 }
{ "_id" : ObjectId("5de5ac646bba334fecac2f30"), "code+2" : 5, "code*2*2*2" : 24, "code%3" : 0 }
{ "_id" : ObjectId("5de647f5b4cd9b14f46e0e30"), "code+2" : 4, "code*2*2*2" : 16, "code%3" : 2 }
>
1.2.3、日期表达式
聚合框架中包含了一些用于提取日期信息的表达式:"$year"、"$month"、"$dayOfMonth"、"$dayOfWeek"、"$dayOfYear"、"$hour"、"$minute"、"$second"。只能对日期类型的字段进行日期操作,不能对数值类型的字段做日期操作。
使用示例:
> db.city.aggregate({"$project":{"crete_year":{"$year":"$create_date"}, "create_week":{"$dayOfWeek":"$create_date"}}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "crete_year" : null, "create_week" : null }
{ "_id" : ObjectId("5de5ac646bba334fecac2f30"), "crete_year" : null, "create_week" : null }
{ "_id" : ObjectId("5de647f5b4cd9b14f46e0e30"), "crete_year" : 2019, "create_week" : 5 }
>
1.2.4、字符串表达式
字符串操作如下:
- "$substr":[ expr, startOffset, numToReturn ]。这个操作会截取字符串的字串,startOffset为字节偏移量,- - - numToReturn为字节数,expr为输入字符串。
- "$concat":[ expr1, [ , expr2, … , exprN ] ]。将给定的字符串连接在一起返回结果;
- "$toLower":expr。返回expr字符串的小写形式;
- "$toUpper":expr。返回expr字符串的大写形式;
使用示例:
> db.city.aggregate({"$project":{"country_city":{"$concat":["$country","-","$name"]}}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "country_city" : "中国-北京" }
{ "_id" : ObjectId("5de5ac646bba334fecac2f30"), "country_city" : "中国-广州" }
{ "_id" : ObjectId("5de647f5b4cd9b14f46e0e30"), "country_city" : "中国-上海" }
>
1.2.5、逻辑表达式
比较表达式:
- "$cmp":[ expr1, expr2 ]。比较expr1和expr2。若相等,返回0;若expr1<expr2,返回负数;若expr1>expr2则返回正数。
- "$strcasecmp":[ string1, string2]。比较string1和string2,区分大小写。只对罗马字符组成的字符串有效。
- "$eq"、"$ne"、"$gt"、"$gte"、"$lt"、"$lte":[ expr1, expr2 ]。对expr1和expr2执行相应的比较操作,返回比较的结果(true或false)。
布尔表达式:
- "$and":[ expr1, [ , expr2, … , exprN ] ]。如果所有表达式的值都是true,那就返回true,否则返回false;
- "$or":[ expr1, [ , expr2, … , exprN ] ]。只要有任意表达式为true,则返回true,否则返回false。
- "$not":expr。对expr取反。
控制语句:
- "$cond":[ booleanExpr, trueExpr, falseExpr]。如果booleanExpr的值时true,那就返回trueExpr,否则返回falseExpr。
- "$ifNull":[ expr, replacementExpr]。如果expr是null,返回replacementExpr,否则返回expr。
使用示例:
> db.city.aggregate({"$project":{"hugeCity":{"$eq":["$name","北京"]}}})
{ "_id" : ObjectId("5de52e826bba334fecac2f28"), "hugeCity" : true }
{ "_id" : ObjectId("5de5ac646bba334fecac2f30"), "hugeCity" : false }
{ "_id" : ObjectId("5de647f5b4cd9b14f46e0e30"), "hugeCity" : false }
>
1.3、$group
$group操作可以将文档依据特定字段的不同值进行分组。