理解

mongo聚合类似关系型数据库的分组操作,

mongo聚合操作是一种管道操作,每一步的结果都是下一步的操作的输入。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Criteria作为检索条件
Criteria criteria = Criteria.where("orgId").is(formReplyModel.getOrgId());
criteria.and("formId").in(formReplyModel.getFormId());
criteria.and("formName").regex("^.*" + formReplyModel.getFormName() + ".*$");
// 创建一个聚合操作的list,后续执行聚合的时候按list的0,1,2...的顺序执行
List<AggregationOperation> operations = new ArrayList<>();
// 第一步,先where
operations.add(Aggregation.match(criteria));
// 第二部,会将where结果基础上进行分组,按createrId分组,获取每组的件数fillCount,
operations.add(Aggregation.group("createrId").count().as("fillCount").max("createdTime").as("LastFillTime").first("staffName").as("staffName").first("createrId").as("userId"));
// 第三部,重点,分组后结果作为此步的输入,取数据总的件数。也就是分页用的总件数
operations.add(Aggregation.count().as("dataCount"));
// 生成聚合实例
Aggregation aggregation = newAggregation(operations);

Integer count = 0;
// 执行聚合操作
AggregationResults<Map> aggregationResults = mongoTemplate.aggregate(aggregation, "form_reply", Map.class);
List<Map> list = aggregationResults.getMappedResults();
if (CollectionUtil.isNotEmpty(list)) {
Map<String,Integer> map = list.get(0);
// 获取结果的总件数
count = (Integer)map.get("dataCount");
}
// 作为放到分页的总件数
page.setTotal(count);
if (count > 0) {
// 将这部操作去掉operations.add(Aggregation.count().as("dataCount"));
operations.remove(operations.size()-1);
// 将分组后的数据按LastFillTime排序
operations.add(Aggregation.sort(Sort.by(Sort.Direction.DESC, "LastFillTime")));
if (formReplyModel.getPageNum() != null && formReplyModel.getPageSize() != null) {
// 分页操作,skip+limit
operations.add(Aggregation.skip((long)(((formReplyModel.getPageNum()) - 1)*formReplyModel.getPageSize())));
operations.add(Aggregation.limit(formReplyModel.getPageSize()));
}
// 生成新的聚合实例
aggregation = newAggregation(operations);
// 执行聚合操作管道流
AggregationResults<FormUserSummaryModel> form_reply = mongoTemplate.aggregate(aggregation, "form_reply", FormUserSummaryModel.class);
List<FormUserSummaryModel> mappedResults = form_reply.getMappedResults();
// 将结果放到分页数据中
page.setRecords(mappedResults);
}

上面例子执行了两次聚合管道操作,第一次获取数据的件数,第二次获取分页数据;将数据进行分组,然后取分页信息。

先分组,再where,其实也就类似与关系型数据库的group by 后再having

先where,再分组,类似与关系型数据库的 where后再group by