すのはら荘春原庄的雪

mongodb聚合在Java中的使用(包含mongo多表关联查询)

B1nbin·2022-07-20 15:11·4430 次阅读

mongodb聚合在Java中的使用(包含mongo多表关联查询)

使用前首先需要配置好MongoTemplate,(详细参考:MongoTemplate的使用

配置好后在类中注入MongoTemplate对象

Copy
@Autowired private MongoTemplate mongoTemplate;

常用函数#

使用前我们先来了解一下常用的函数

  1. Aggregation.group() : 聚合函数,将某个字段或者某个数组作为分组统计的依据,在group的基础上又扩展出以下函数:

    • sum() : 求和
    • max() : 获取最大值
    • min() : 获取最小值
    • avg() : 获取平均值
    • count() : 统计条目数
    • first () : 获取group by 后的某个字段的首个值
    • last() : 获取 group by 后的某个字段的最后一个值
    • push() : 在结果文档中插入值到一个数组中
    • addToSet() : 在结果文档中插入值到一个数组中,但不创建副本(作为集合)。
  2. Aggregation.match() : 过滤函数,主要存储过滤数据的条件,输出符合条件的记录

  3. Aggregation.project(): 修改数据结构函数,将前面管道中的获取的字段进行重名,增加,修改字段等操作。

  4. Aggregation.unwind():将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。当preserveNullAndEmptyArrays为true时,将包括字段为null,空,或者缺失的数据;

  5. Aggregation.sort(): 排序函数,将上级管道的内容按照某个字段进行排序并且输出。值为1升、-1降。sort一般放在group后,也就是说得到结果后再排序,如果先排序再分组没什么意义;

  6. Aggregation.limit(): 限制输出函数,将聚合返回的内容限定在某个条目之内。通常作为页面大小

  7. Aggregation.skip(): 跳过指定数量的条目再开始返回数据的函数,通常和sort(),limit()配合,实现数据翻页查询等操作。

  8. Aggregation.lookup(): 连表查询,将被关联集合添加到执行操作的集合中。

实际用例#

用accountId和status做group操作

Copy
mongodb: db.getCollection('mro_fn_subscribes').aggregate([ { $group:{ "_id":{"_id":"$accountId", "status": "$status" }, "count":{"$sum": NumberInt(1)}, "statusSum":{"$sum": "$status"}, "codeAvg":{"$avg":"$fnCode"}, "codeMax":{"$max":"$fnCode"}, "codeMin":{"$min":"$fnCode"}, "codeFirst":{"$first":"$fnCode"}, "codeLast":{"$last":"$fnCode"}, } } ]) java: Aggregation aggregation = Aggregation.newAggregation( Aggregation.group("accountId", "status") .count().as("count") .sum("status").as("statusSum") .avg("fnCode").as("codeAvg") .max("fnCode").as("codeMax") .min("fnCode").as("codeMin") .first("fnCode").as("codeFirst") .last("fnCode").as("codeLast") );

match管道过滤:

Copy
mongodb: db.getCollection('mro_fn_subscribes').aggregate( {$match:{userId:"a"}} ) java: Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(new Criteria().and("userId").is("a") );

project筛选字段:

Copy
mongo: db.getCollection('mro_fn_subscribes').aggregate([ { "$group" : { "_id" : "$_id", "num" : { "$sum" : "$num" }, "firstName" : { "$first" : "$name" }, "lastName" : { "$last" : "$name" } } }, { "$project" : { "_id" : 1, "num" : 1, "firstName" : 1, "name" : "$lastName" } } ]) java: // 初始化聚合 Aggregation aggregation = 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") // 重新命名字段 );

unwind拆分数组

Copy
mongo: db.col.aggregate( { $match:{userid:"a"} }, { $unwind:{ path:"$items", includeArrayIndex: "arrayIndex" } } ) java: Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(new Criteria().and("userId").is("a"), Aggregation.unwind("items",true) );

sort skip limit处理数据:

Copy
Mongo: db.getCollection('mro_fn_subscribes').aggregate([ { "$group" : { _id:{"_id":"$accountId", "status": "$status" } } }, { "$sort" : { "num" : -1 } }, { "$skip" : NumberInt(10) }, { "$limit" : NumberInt(2) } ] ) Java: Aggregation aggregation = Aggregation.newAggregation( Aggregation.group("accountId", "status") Aggregation.sort(Direction.DESC, "num"), //将num降序 Aggregation.skip(10), //从第10条记录开始 Aggregation.limit(2) //取两条数据 );

lookup多表关联查询:

Copy
# Mongo: db.getCollection('mro_accounts').aggregate([ { $lookup: { from:"mro_profiles", # 被关联表名 localField:"userName", # 主表(mro_accounts)中用于关联的字段 foreignField:"mobile", # 被关联表(mro_profiles)中用于关联的字段 as:"profileDoc" # 被关联的表的别名 } } ]) # Java Aggregation aggregation = Aggregation.newAggregation( Aggregation.lookup("mro_profiles", "userName", "mobile", "profileDoc") //分别对应from, localField, foreignField, as );

获取查询结果#

在创建好Aggregation对象之后,再用 mongotemplate.aggregate(aggregation, "mro_fn_subscribes", Fnsubscribe.class).getMappedResults() 获取查询的对象列表

posted @   B1nbin  阅读(4430)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
/*
*/
点击右上角即可分享
微信分享提示
目录