Spring Data MongoDB 教程

聚合管道更新

MongoOperations 和 ReactiveMongoOperations 暴露的更新方法也通过 AggregationUpdate 接受一个聚合管道。使用 AggregationUpdate 可以在更新操作中利用 MongoDB 4.2 聚合。在更新中使用聚合允许通过用单个操作表达多个阶段和多个条件来更新一个或多个字段。

更新可包括以下阶段:

  • AggregationUpdate.set(…).toValue(…) → $set : { … }

  • AggregationUpdate.unset(…) → $unset : [ … ]

  • AggregationUpdate.replaceWith(…) → $replaceWith : { … }

示例

本示例通过向 MongoDB 插入三个员工 Worker 文档,包含姓名、年龄和截止本年薪水。然后通过聚合管道计算每人的平均薪水,最后根据薪水计算它们薪水等级。

(1)工人实体 Worker 代码

package com.hxstrive.springdata.mongodb.entity;

import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import java.util.List;

/**
* 工人实体
* @author hxstrive.com 2022/12/29
*/
@Data
@Builder
@ToString
public class Worker {
   /** 工人编号 */
   private String id;
   /** 姓名 */
   private String name;
   /** 年龄 */
   private int age;
   /** 本年度薪水 */
   private List<Float> salarys;
}

(2)客户端,通过 MongoTemplate 实现聚合管道计算平均值等。

package com.hxstrive.springdata.mongodb;

import com.hxstrive.springdata.mongodb.entity.Worker;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import java.util.Arrays;

@SpringBootTest
class AggregationUpdateTest {

   @Autowired
   private MongoTemplate mongoTemplate;

   @Test
   void contextLoads() {
       // 删除集合
       mongoTemplate.dropCollection(Worker.class);

       // 准备数据
       // 插入三个工人数据,以及本年度前四个月的薪水
       mongoTemplate.insert(Worker.builder().name("Joe").age(28)
               .salarys(Arrays.asList(5050f, 4980f, 5200f, 5150f)).build());
       mongoTemplate.insert(Worker.builder().name("Tom").age(30)
               .salarys(Arrays.asList(7000f, 6900f, 7200f, 8100f)).build());
       mongoTemplate.insert(Worker.builder().name("Helen").age(31)
               .salarys(Arrays.asList(5500f, 4900f, 6200f, 5300f)).build());

       // 通过聚合运算计算工人本年度前四个月的平均薪水
       // 以及根据平均薪水判断工人薪水标准
       AggregationUpdate update = Aggregation.newUpdate()
               .set("average").toValue(ArithmeticOperators.valueOf("salarys").avg())
               .set("grade").toValue(ConditionalOperators.switchCases(
                       // 根据前面计算的平均值判断标准
                       ConditionalOperators.Switch.CaseOperator.when(
                               ComparisonOperators.Gt.valueOf("average").greaterThanValue(50000)).then("富有"),
                       ConditionalOperators.Switch.CaseOperator.when(
                               ComparisonOperators.Gt.valueOf("average").greaterThanValue(10000)).then("中产"),
                       ConditionalOperators.Switch.CaseOperator.when(
                               ComparisonOperators.Gt.valueOf("average").greaterThanValue(7000)).then("低产")
               ).defaultTo("贫穷"));

       // 进行更新
       mongoTemplate.update(Worker.class)
               .apply(update)
               .all();
   }

}

运行代码,查询 MongoDB 中的文档,数据如下:

/* 1 createdAt:2022/12/29 下午1:09:50*/
{
    "_id" : ObjectId("63ad211e8f1e061840b1af08"),
    "name" : "Helen",
    "age" : 31,
    "salarys" : [
        5500,
        4900,
        6200,
        5300
    ],
    "average" : 5475,
    "grade" : "贫穷"
},
....

上面代码对应的 MongoDB 命令如下:

// 向工人集合插入三条数据
db.worker.insertMany( [
  { "name": "Helen", "age": 31, "salarys" : [5500, 4900, 6200, 5300] },
  { "name": "Tom", "age": 30, "salarys" : [7000, 6900, 7200, 8100] },
  { "name": "Joe", "age": 28, "salarys" : [5050, 4980, 5200, 5150] },
])

// 查看工人集合数据
db.worker.find({})

// 使用聚合管道计算薪水平均值和平均薪水的等级
db.worker.update(
  { },
  [
    { $set: { average : { $trunc: [ { $avg: "$salarys" }, 0 ] } } },
    { $set: { grade: {
       $switch: {
          branches: [
              { case: { $gte: [ "$average", 50000 ] }, then: "富有" },
              { case: { $gte: [ "$average", 10000 ] }, then: "中产" },
              { case: { $gte: [ "$average", 7000 ] }, then: "低产" }
          ],
          default: "贫穷"
       }
       
    } } }
  ],
  { multi: true }
)

// 继续查看计算后的工人集合数据
db.worker.find({})

下面是集合中的数据,如下:

/* 1 createdAt:2022/12/29 下午1:09:50*/
{
    "_id" : ObjectId("63ad211e8f1e061840b1af08"),
    "name" : "Helen",
    "age" : 31,
    "salarys" : [
        5500,
        4900,
        6200,
        5300
    ],
    "average" : 5475,
    "grade" : "贫穷"
},

/* 2 createdAt:2022/12/29 下午1:09:50*/
{
    "_id" : ObjectId("63ad211e8f1e061840b1af09"),
    "name" : "Tom",
    "age" : 30,
    "salarys" : [
        7000,
        6900,
        7200,
        8100
    ],
    "average" : 7300,
    "grade" : "低产"
},

/* 3 createdAt:2022/12/29 下午1:09:50*/
{
    "_id" : ObjectId("63ad211e8f1e061840b1af0a"),
    "name" : "Joe",
    "age" : 28,
    "salarys" : [
        5050,
        4980,
        5200,
        5150
    ],
    "average" : 5095,
    "grade" : "贫穷"
}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号