该示例演示如何在投影操作中使用简单的算术运算。关键代码如下:
(1)产品实体代码
public class Product {
// 产品ID
private String id;
// 产品名称
private String name;
// 净价
private double netPrice;
// 单位
private int spaceUnits;
}(2)投影操作关键代码
TypedAggregation<Product> agg = newAggregation(Product.class,
project("name", "netPrice")
.and("netPrice").plus(1).as("netPricePlus1")
.and("netPrice").minus(1).as("netPriceMinus1")
.and("netPrice").multiply(1.19).as("grossPrice")
.and("netPrice").divide(2).as("netPriceDiv2")
.and("spaceUnits").mod(2).as("spaceUnitsMod2")
);
AggregationResults<Document> result = mongoTemplate.aggregate(agg, Document.class);
List<Document> resultList = result.getMappedResults();
for(Document doc : resultList) {
System.out.println(JSONObject.toJSONString(doc));
}注意,我们从传递给 newAggregation() 方法的第一个参数 Product 类派生输入集合的名称,因此在调用 mongoTemplate.aggregate() 时不需要指定输入文档类型。
(1)application.properties 配置
# Log logging.level.root=debug # MongoDB spring.data.mongodb.uri=mongodb://localhost:27017/test
(2)AppConfig.java 配置类
package com.hxstrive.springdata.mongodb.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
/**
* 配置 MongoTemplate
* @author hxstrive.com 2022/12/23
*/
@Slf4j
@Configuration
public class AppConfig {
@Bean
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
log.info("mongoTemplate({}, {})", mongoDatabaseFactory);
return new MongoTemplate(mongoDatabaseFactory);
}
}(3)映射给定的输入集合的结构
import lombok.Builder;
import lombok.Data;
/**
* 产品实体
* @author hxstrive.com
*/
@Data
@Builder
public class Product {
// 产品ID
private String id;
// 产品名称
private String name;
// 净价
private double netPrice;
// 单位
private int spaceUnits;
}(4)投影结果映射的实体
import lombok.Data;
/**
* 结果映射实体
* @author hxstrive.com
*/
@Data
public class Document {
private String id;
private String name;
private double netPrice;
private int spaceUnits;
private double netPricePlus1;
private double netPriceMinus1;
private double grossPrice;
private double netPriceDiv2;
private int spaceUnitsMod2;
}(5)客户端代码,通过 MongoTemplate 实现分组和投影。
package com.hxstrive.springdata.mongodb;
import com.alibaba.fastjson.JSONObject;
import com.hxstrive.springdata.mongodb.entity.demo4.Document;
import com.hxstrive.springdata.mongodb.entity.demo4.Product;
import org.junit.jupiter.api.BeforeEach;
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.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import java.util.List;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
/**
* 聚合框架示例4
* @author hxstrive.com
*/
@SpringBootTest
public class AggregationFrameworkDemo4 {
@Autowired
private MongoTemplate mongoTemplate;
@BeforeEach
public void init() {
mongoTemplate.dropCollection(Product.class);
// 准备数据
mongoTemplate.insert(Product.builder().id("100").name("A").netPrice(100).spaceUnits(10).build());
mongoTemplate.insert(Product.builder().id("200").name("B").netPrice(200).spaceUnits(20).build());
mongoTemplate.insert(Product.builder().id("300").name("C").netPrice(300).spaceUnits(30).build());
mongoTemplate.insert(Product.builder().id("400").name("D").netPrice(400).spaceUnits(40).build());
}
@Test
public void contextLoads() {
TypedAggregation<Product> agg = newAggregation(Product.class,
project("name", "netPrice")
.and("netPrice").plus(1).as("netPricePlus1")
.and("netPrice").minus(1).as("netPriceMinus1")
.and("netPrice").multiply(1.19).as("grossPrice")
.and("netPrice").divide(2).as("netPriceDiv2")
.and("spaceUnits").mod(2).as("spaceUnitsMod2")
);
AggregationResults<Document> result = mongoTemplate.aggregate(agg, Document.class);
List<Document> resultList = result.getMappedResults();
for(Document doc : resultList) {
System.out.println(JSONObject.toJSONString(doc));
}
// 结果:
// {"grossPrice":119.0,"id":"100","name":"A","netPrice":100.0,"netPriceDiv2":50.0,"netPriceMinus1":99.0,"netPricePlus1":101.0,"spaceUnits":0,"spaceUnitsMod2":0}
// {"grossPrice":238.0,"id":"200","name":"B","netPrice":200.0,"netPriceDiv2":100.0,"netPriceMinus1":199.0,"netPricePlus1":201.0,"spaceUnits":0,"spaceUnitsMod2":0}
// {"grossPrice":357.0,"id":"300","name":"C","netPrice":300.0,"netPriceDiv2":150.0,"netPriceMinus1":299.0,"netPricePlus1":301.0,"spaceUnits":0,"spaceUnitsMod2":0}
// {"grossPrice":476.0,"id":"400","name":"D","netPrice":400.0,"netPriceDiv2":200.0,"netPriceMinus1":399.0,"netPricePlus1":401.0,"spaceUnits":0,"spaceUnitsMod2":0}
// 执行的语句如下:
// [{ "$project" : { "name" : 1, "netPrice" : 1,
// "netPricePlus1" : { "$add" : ["$netPrice", 1]},
// "netPriceMinus1" : { "$subtract" : ["$netPrice", 1]},
// "grossPrice" : { "$multiply" : ["$netPrice", 1.19]},
// "netPriceDiv2" : { "$divide" : ["$netPrice", 2]},
// "spaceUnitsMod2" : { "$mod" : ["$spaceUnits", 2]}
// }
// }]
}
}