/springboot/springboot-mongodb-example/src/main/java/mydlq/club/example/service/aggregate/AggregatePipelineService.java

https://github.com/my-dlq/blog-example · Java · 157 lines · 90 code · 11 blank · 56 comment · 6 complexity · 097713c8d1da34584b534264ae24d5a9 MD5 · raw file

  1. package mydlq.club.example.service.aggregate;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.data.domain.Sort;
  4. import org.springframework.data.mongodb.core.MongoTemplate;
  5. import org.springframework.data.mongodb.core.aggregation.Aggregation;
  6. import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
  7. import org.springframework.data.mongodb.core.aggregation.AggregationResults;
  8. import org.springframework.data.mongodb.core.query.Criteria;
  9. import org.springframework.stereotype.Service;
  10. import javax.annotation.Resource;
  11. import java.util.Map;
  12. /**
  13. * 聚合管道操作符
  14. *
  15. * @author mydlq
  16. */
  17. @Slf4j
  18. @Service
  19. public class AggregatePipelineService {
  20. /**
  21. * 设置集合名称
  22. */
  23. private static final String COLLECTION_NAME = "users";
  24. @Resource
  25. private MongoTemplate mongoTemplate;
  26. /**
  27. * 使用 $group 和 $match 聚合,先使用 $match 过滤文档,然后再使用 $group 进行分组
  28. *
  29. * @return 聚合结果
  30. */
  31. public Object aggregateGroupMatch() {
  32. // 设置聚合条件,先使用 $match 过滤岁数大于 25 的用户,然后按性别分组,统计每组用户工资最高值
  33. AggregationOperation match = Aggregation.match(Criteria.where("age").lt(25));
  34. AggregationOperation group = Aggregation.group("sex").max("salary").as("sexSalary");
  35. // 将操作加入到聚合对象中
  36. Aggregation aggregation = Aggregation.newAggregation(match, group);
  37. // 执行聚合查询
  38. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  39. for (Map result : results.getMappedResults()) {
  40. log.info("{}", result);
  41. }
  42. return results.getMappedResults();
  43. }
  44. /**
  45. * 使用 $group 和 $sort 聚合,先使用 $group 进行分组,然后再使用 $sort 排序
  46. *
  47. * @return 聚合结果
  48. */
  49. public Object aggregateGroupSort() {
  50. // 设置聚合条件,按岁数分组,然后统计每组用户工资最大值和用户数,按每组用户工资最大值升序排序
  51. AggregationOperation group = Aggregation.group("age")
  52. .max("salary").as("ageSalary")
  53. .count().as("ageCount");
  54. AggregationOperation sort = Aggregation.sort(Sort.by("ageSalary").ascending());
  55. // 将操作加入到聚合对象中
  56. Aggregation aggregation = Aggregation.newAggregation(group, sort);
  57. // 执行聚合查询
  58. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  59. for (Map result : results.getMappedResults()) {
  60. log.info("{}", result);
  61. }
  62. return results.getMappedResults();
  63. }
  64. /**
  65. * 使用 $group 和 $limit 聚合,先使用 $group 进行分组,然后再使用 $limit 限制一定数目文档
  66. *
  67. * @return 聚合结果
  68. */
  69. public Object aggregateGroupLimit() {
  70. // 设置聚合条件,先按岁数分组,然后求每组用户的工资总数、最大值、最小值、平均值,限制只能显示五条
  71. AggregationOperation group = Aggregation.group("age")
  72. .sum("salary").as("sumSalary")
  73. .max("salary").as("maxSalary")
  74. .min("salary").as("minSalary")
  75. .avg("salary").as("avgSalary");
  76. AggregationOperation limit = Aggregation.limit(5L);
  77. // 将操作加入到聚合对象中
  78. Aggregation aggregation = Aggregation.newAggregation(group, limit);
  79. // 执行聚合查询
  80. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  81. for (Map result : results.getMappedResults()) {
  82. log.info("{}", result);
  83. }
  84. return results.getMappedResults();
  85. }
  86. /**
  87. * 使用 $group 和 $skip 聚合,先使用 $group 进行分组,然后再使用 $skip 跳过一定数目文档
  88. *
  89. * @return 聚合结果
  90. */
  91. public Object aggregateGroupSkip() {
  92. // 设置聚合条件,先按岁数分组,然后求每组用户的工资总数、最大值、最小值、平均值,跳过前 2 条
  93. AggregationOperation group = Aggregation.group("age")
  94. .sum("salary").as("sumSalary")
  95. .max("salary").as("maxSalary")
  96. .min("salary").as("minSalary")
  97. .avg("salary").as("avgSalary");
  98. AggregationOperation limit = Aggregation.skip(2L);
  99. // 将操作加入到聚合对象中
  100. Aggregation aggregation = Aggregation.newAggregation(group, limit);
  101. // 执行聚合查询
  102. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  103. for (Map result : results.getMappedResults()) {
  104. log.info("{}", result);
  105. }
  106. return results.getMappedResults();
  107. }
  108. /**
  109. * 使用 $group 和 $project 聚合,先使用 $group 进行分组,然后再使用 $project 限制显示的字段
  110. *
  111. * @return 聚合结果
  112. */
  113. public Object aggregateGroupProject() {
  114. // 设置聚合条件,按岁数分组,然后求每组用户工资最大值、最小值,然后使用 $project 限制值显示 salaryMax 字段
  115. AggregationOperation group = Aggregation.group("age")
  116. .max("salary").as("maxSalary")
  117. .min("salary").as("minSalary");
  118. AggregationOperation project = Aggregation.project("maxSalary");
  119. // 将操作加入到聚合对象中
  120. Aggregation aggregation = Aggregation.newAggregation(group, project);
  121. // 执行聚合查询
  122. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  123. for (Map result : results.getMappedResults()) {
  124. log.info("{}", result);
  125. }
  126. return results.getMappedResults();
  127. }
  128. /**
  129. * 使用 $group 和 $unwind 聚合,先使用 $project 进行分组,然后再使用 $unwind 拆分文档中的数组为一条新文档记录
  130. *
  131. * @return 聚合结果
  132. */
  133. public Object aggregateProjectUnwind() {
  134. // 设置聚合条件,设置显示`name`、`age`、`title`字段,然后将结果中的多条文档按 title 字段进行拆分
  135. AggregationOperation project = Aggregation.project("name", "age", "title");
  136. AggregationOperation unwind = Aggregation.unwind("title");
  137. // 将操作加入到聚合对象中
  138. Aggregation aggregation = Aggregation.newAggregation(project, unwind);
  139. // 执行聚合查询
  140. AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
  141. for (Map result : results.getMappedResults()) {
  142. log.info("{}", result);
  143. }
  144. return results.getMappedResults();
  145. }
  146. }