版权声明:本文为神州灵云作者的原创文章,未经神州灵云允许不得转载。
本文作者:Lux
#前言:
接触mongo也有段时间了,在进行功能研发时经常用到mongo聚合查询,所以想整理一下mongo常用的聚合查询的函数,以及在java中实现的语法。也便于以后做一些简单的查询时有个例子可以参考 (fu zhi)。很多复杂的查询都是从简单的部分组合的,同时查询很多内容的话,用聚合管道进行字段筛选之后,再处理数据时会方便很多,也便于优化查询语句时的观看体验。
#1 前提配置:
##1.1 连接配置,使用自动配置方式,在applicaiton.properties中配置连接信息即可
spring.data.mongodb.host= ip
spring.data.mongodb.port= port
spring.data.mongodb.database = mongdbname
##1.2 java中使用
注入mongoTemplate对象 :
@Autowired
private MongoTemplate mongoTemplate;
#2 Aggregation常用函数
##2.1 Aggregation.group() : 聚合函数,将某个字段或者某个数组作为分组统计的依据,在group的基础上又扩展出以下函数:
2.1.1:sum() : 求和
2.1.2:max() : 获取最大值
2.1.3:min() : 获取最小值
2.1.4:avg() : 获取平均值
2.1.5:count() : 统计条目数
2.1.6: first () : 获取group by 后的某个字段的首个值
2.1.7:last() : 获取 group by 后的某个字段的最后一个值
##2.2 Aggregation.match() : 过滤函数,主要存储过滤数据的条件,输出符合条件的记录
##2.3 Aggregation.project(): 修改数据结构函数,将前面管道中的获取的字段进行重名,增加,修改字段等操作。
##2.4 Aggregation.sort(): 排序函数,将上级管道的内容按照某个字段进行排序并且输出。
##2.5 Aggregation.limit(): 限制输出函数,将聚合返回的内容限定在某个条目之内。
##2.6 Aggregation.skip(): 跳过指定数量的条目再开始返回数据的函数,通常和sort(),limit()配合,实现数据翻页查询等操作。
#3 查询主体:
##3.1 group by 聚合查询
3.1.1:对id做group
mongodb:
db.table.aggregate([
{
"$group" : {
"_id" : "$_id"
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"id"})
);
当然,单纯的做group by 不做输出大多数没啥用,一般都是配合输出函数来使用group by的。
3.1.2:以id为group by计算num的总值sum()
Mongo:
db.table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$sum" : "$num"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).sum("num").as("num")
);
3.1.3:以id为group by找出num的最大值max()
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$max" : "$num"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).max("num").as("num")
);
3.1.4:以id为group by找出num的最小值min()
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$min" : "$num"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).min("num").as("num")
);
3.1.5:以id为group by计算num的平均值avg()
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$avg" : "$num"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).avg("num").as("num")
);
3.1.6:对id做记数统计count()
Mongo:
db.table.aggregate([
{
"$group" : {
"_id" : "$_id",
"count" : {
"$sum" : NumberInt(1)
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).count().as("count")
);
3.1.7:以id为group by获取name的第一个值first()
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"name" : {
"$first" : "$name"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).first("name").as("name")
);
3.1.8:以id为group by获取name的最后一个值last()
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"name" : {
"$last" : "$name"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).last("name").as("name")
);
3.1.9:组合一下,以id为group by获取num的和(sum)以及name的第一个值(first)
Mongo:
db. table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$sum" : "$num"
},
"name" : {
"$first" : "$name"
}
}
}
])
java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).
sum("num").as("num").
first("name").as("name")
);
##3.2 match管道过滤
Match中设置的是记录的过滤条件。过滤条件参考Criteria的使用
举个例子:
Mongo:
db. table.aggregate([
{
"$match" : {
"$and" : [
{
"_id" : {
"$exists" : true
}
}
]
}
},
{
"$group" : {
"_id" : "$_id",
"num" : {
"$sum" : "$num"
},
"name" : {
"$first" : "$name"
}
}
}
])
Java:
//定义Criteria类集合
List<Criteria> where = new ArrayList<Criteria>();
//添加条件
where.add(new Criteria().where("_id").exists(true));
//初始化聚合
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(new Criteria().andOperator((Criteria[]) where.
toArray(new Criteria[where.size()]))),
Aggregation.group(new String[] {"_id"}).sum("num").as("num").first("name").as("name")
);
##3.3 Aggregation.project()筛选需要的字段
举个例子:按照_id group by,然后将num做取和处理,获取name的first值和last值,再用project将id,firstName,num取出,并且将lastName重命名为name
Mongo:
db.table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$sum" : "$num"
},
"firstName" : {
"$first" : "$name"
},
"lastName" : {
"$last" : "$name"
}
}
},
{
"$project" : {
"_id" : NumberInt(1),
"num" : NumberInt(1),
"firstName" : NumberInt(1),
"name" : "$lastName"
}
}
])
Java:
//初始化聚合
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).sum("num").as("num").
first("name").as("firstName").
last("name").as("lastName"),
Aggregation.project("_id", "num", "firstName").
and("lastName").as("name")//重新挑选字段
);
##3.4 sort,limit,skip组合使用
举个例子:将id聚合,然后将num做求和处理。并且将sum(num)的值进行降序排序,跳过前十条记录后,取出前两条记录。
Mongo:
db.table.aggregate([
{
"$group" : {
"_id" : "$_id",
"num" : {
"$sum" : "$num"
}
}
},
{
"$sort" : {
"num" : NumberInt(-1)
}
},
{
"$skip" : NumberInt(10)
},
{
"$limit" : NumberInt(2)
}
]
)
Java:
Aggregation agg = Aggregation.newAggregation(
Aggregation.group(new String[] {"_id"}).sum("num").as("num").
first("name").as("firstName").
last("name").as("lastName"),
Aggregation.sort(Direction.DESC, "num"), //将num降序
Aggregation.skip(10), //从第10条记录开始
Aggregation.limit(2) //取两条数据
);
对于mongo的聚合管道还有一些函数,比如
$unwind
:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$cond
: 将文档中的值做if操作,满足的进行某项分支,不满足的进行另一项统计。
$goNear
:$goNear会返回一些坐标值,这些值以按照距离指定点距离由近到远进行排序。
等等。