MongoDB聚合框架旨在对文档进行分组并将其转换为聚合结果。 聚合查询包括定义将在管道中执行的几个阶段。 如果您对有关该框架的更深入的细节感兴趣,那么
mongodb docs是一个很好的起点。

这篇文章的重点是编写一个用于查询mongodb的Web应用程序,以便从数据库中获取汇总结果。 借助Spring Boot和Spring Data,我们将以非常简单的方式进行操作。 实际上,实现该应用程序确实非常快,因为Spring Boot会处理所有必要的设置,而Spring Data将帮助我们配置存储库。

可以在我的Github存储库中找到源代码。

1申请

在遍历代码之前,让我们看一下我们要对应用程序执行的操作。

我们的领域是我们分布在多个仓库中的产品的集合:

@Document
public class Product {@Idprivate final String id;private final String warehouse;private final float price;public Product(String id, String warehouse, float price) {this.id = id;this.warehouse = warehouse;this.price = price;}public String getId() {return id;}public String getWarehouse() {return warehouse;}public float getPrice() {return price;}
}

我们的目标是收集价格范围内的所有产品,并按仓库分组,并收集总收入和每个分组的平均价格。

在此示例中,我们的仓库存储以下产品:

new Product("NW1", "Norwich", 3.0f);
new Product("LN1", "London", 25.0f);
new Product("LN2", "London", 35.0f);
new Product("LV1", "Liverpool", 15.2f);
new Product("MN1", "Manchester", 45.5f);
new Product("LV2", "Liverpool", 23.9f);
new Product("LN3", "London", 55.5f);
new Product("LD1", "Leeds", 87.0f);

该应用程序将查询价格在5.0到70.0之间的产品。 所需的聚合管道步骤如下:

我们将最终得到按仓库分组的汇总结果。 每个组将包含每个仓库的产品清单,平均产品价格和总收入,这实际上是价格的总和。

2 Maven依赖

如您所见,我们有一个简短的pom.xml,其中包含Spring Boot依赖项:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.3.3.RELEASE</version><relativePath/>
</parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version>
</properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

通过将spring-boot-starter-parent定义为父pom,我们设置了Spring Boot的默认设置。 主要是它设置了可能使用的一堆库的版本,例如Spring或Apache Commons。 例如,我们正在使用的Spring Boot 1.3.3将4.2.5.RELEASE设置为Spring框架版本。 如前几篇文章所述,它没有将库添加到我们的应用程序中,而只是设置版本。

定义父项后,我们只需添加三个依赖项:

  • spring-boot-starter-web:主要包括Spring MVC库和嵌入式Tomcat服务器。
  • spring-boot-starter-test:包括JUnit,Mockito,Hamcrest和Spring Test等测试库。
  • spring-boot-starter-data-mongodb:此依赖项包括MongoDB Java驱动程序和Spring Data Mongo库。

3应用程序设置

多亏了Spring Boot,应用程序设置与依赖项设置一样简单:

@SpringBootApplication
public class AggregationApplication {public static void main(String[] args) {SpringApplication.run(AggregationApplication.class, args);}
}

运行main方法时,我们将启动侦听8080端口的Web应用程序。

4资料库

既然我们已经正确配置了应用程序,我们就可以实现存储库。 这也不难,因为Spring Data负责所有布线。

@Repository
public interface ProductRepository extends MongoRepository<Product, String> {}

以下测试证明我们的应用程序已正确设置。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = AggregationApplication.class)
@WebAppConfiguration
public class AggregationApplicationTests {@Autowiredprivate ProductRepository productRepository;@Beforepublic void setUp() {productRepository.deleteAll();}@Testpublic void contextLoads() {}@Testpublic void findById() {Product product = new Product("LN1", "London", 5.0f);productRepository.save(product);Product foundProduct = productRepository.findOne("LN1");assertNotNull(foundProduct);}
}

我们没有实现save和findOne方法。 由于我们的存储库正在扩展MongoRepository,因此已经定义了它们。

5聚合查询

最后,我们设置了应用程序并解释了所有步骤。 现在我们可以专注于聚合查询。

由于我们的聚合查询不是基本查询,因此我们需要实现一个自定义存储库。 这些步骤是:

使用我们需要的方法创建自定义存储库:

public interface ProductRepositoryCustom {List<WarehouseSummary> aggregate(float minPrice, float maxPrice);
}

修改第一个存储库以扩展我们的自定义存储库:

@Repository
public interface ProductRepository extends MongoRepository<Product, String>, ProductRepositoryCustom {}

创建一个实现来编写聚合查询:

public class ProductRepositoryImpl implements ProductRepositoryCustom {private final MongoTemplate mongoTemplate;@Autowiredpublic ProductRepositoryImpl(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}@Overridepublic List<WarehouseSummary> aggregate(float minPrice, float maxPrice) {...}
}

现在,我们将实现postgo开头所述的mongodb管道阶段。

我们的第一个操作是match操作。 我们将过滤掉超出我们价格范围的所有产品文档:

private MatchOperation getMatchOperation(float minPrice, float maxPrice) {Criteria priceCriteria = where("price").gt(minPrice).andOperator(where("price").lt(maxPrice));return match(priceCriteria);
}

流水线的下一个阶段是组操作。 除了按仓库对文档进行分组之外,在此阶段,我们还进行以下计算:

  • last:返回组中最后一个文档的仓库。
  • addToSet:收集所有分组文档的所有唯一产品ID,从而形成一个数组。
  • 平均:计算组中所有价格的平均值。
  • sum:汇总组中的所有价格。
private GroupOperation getGroupOperation() {return group("warehouse").last("warehouse").as("warehouse").addToSet("id").as("productIds").avg("price").as("averagePrice").sum("price").as("totalRevenue");
}

管道的最后阶段是项目运营。 在这里,我们指定聚合的结果字段:

private ProjectionOperation getProjectOperation() {return project("productIds", "averagePrice", "totalRevenue").and("warehouse").previousOperation();
}

查询的构建如下:

public List<WarehouseSummary> aggregate(float minPrice, float maxPrice) {MatchOperation matchOperation = getMatchOperation(minPrice, maxPrice);GroupOperation groupOperation = getGroupOperation();ProjectionOperation projectionOperation = getProjectOperation();return mongoTemplate.aggregate(Aggregation.newAggregation(matchOperation,groupOperation,projectionOperation), Product.class, WarehouseSummary.class).getMappedResults();
}

在聚合方法中,我们指示输入类,这是我们的产品文档。 下一个参数是输出类,它是一个DTO,用于存储结果聚合:

public class WarehouseSummary {private String warehouse;private List<String> productIds;private float averagePrice;private float totalRevenue;

我们应该通过测试来证明该结果符合我们的预期:

@Test
public void aggregateProducts() {saveProducts();List<WarehouseSummary> warehouseSummaries = productRepository.aggregate(5.0f, 70.0f);assertEquals(3, warehouseSummaries.size());WarehouseSummary liverpoolProducts = getLiverpoolProducts(warehouseSummaries);assertEquals(39.1, liverpoolProducts.getTotalRevenue(), 0.01);assertEquals(19.55, liverpoolProducts.getAveragePrice(), 0.01);
}private void saveProducts() {productRepository.save(new Product("NW1", "Norwich", 3.0f));productRepository.save(new Product("LN1", "London", 25.0f));productRepository.save(new Product("LN2", "London", 35.0f));productRepository.save(new Product("LV1", "Liverpool", 15.2f));productRepository.save(new Product("MN1", "Manchester", 45.5f));productRepository.save(new Product("LV2", "Liverpool", 23.9f));productRepository.save(new Product("LN3", "London", 55.5f));productRepository.save(new Product("LD1", "Leeds", 87.0f));
}private WarehouseSummary getLiverpoolProducts(List<WarehouseSummary> warehouseSummaries) {return warehouseSummaries.stream().filter(product -> "Liverpool".equals(product.getWarehouse())).findAny().get();
}

六,结论

Spring Data与MongoDB聚合框架具有良好的集成。 添加Spring Boot来配置应用程序,让我们集中精力构建查询。 对于构建过程,Aggregation类具有几种静态方法,可帮助我们实现不同的管道阶段。

我正在Google Plus和Twitter上发布我的新帖子。 如果您要更新新内容,请关注我。

翻译自: https://www.javacodegeeks.com/2016/04/data-aggregation-spring-data-mongodb-spring-boot.html

使用Spring Data MongoDB和Spring Boot进行数据聚合相关推荐

  1. 数据聚合Spring Data MongoDB:嵌套结果

    1引言 在上一篇文章中,我们构建了聚合管道的基本示例. 如果您需要有关如何创建项目和配置应用程序的更多详细信息,也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚 ...

  2. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  3. Spring Data MongoDB中的审核实体

    Spring Data MongoDB 1.2.0静默引入了新功能:支持基本审核 . 因为您不会在本文的官方参考中找到太多有关它的信息,所以我将展示它带来的好处,如何配置Spring以进行审计以及如何 ...

  4. 使用NoSQLUnit测试Spring Data MongoDB应用程序

    Spring Data MongoDB是Spring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用MongoDB作为数据库的应用程序. 要使用NoSQLUnit为Spring ...

  5. Spring Data MongoDB示例

    Spring Data MongoDB示例 欢迎使用Spring Data MongoDB示例.Spring Data MongoDB是将Spring Framework与最广泛使用的NoSQL数据库 ...

  6. mongo java 注解,在Java中使用Spring Data MongoDB操作Mong | zifangsky的个人博客

    前言:在上一篇文章中(PS:https://www.zifangsky.cn/923.html)我简单介绍了如何在Linux中安装MongoDB以及MongoDB的增删改查等基本命令用法(PS:更多M ...

  7. mongodb数据库java接口,MongoDB —— 使用Spring Data MongoDB操作数据库

    我们使用Spring Data MongoDB可以方便的在Spring boot项目中操作MongoDB 文档地址:https://docs.spring.io/spring-boot/docs/2. ...

  8. Springboot Could not resolve placeholder ‘spring.data.mongodb.database’ in value “${spring.data.mong

    Springboot Could not resolve placeholder 'spring.data.mongodb.database' in value "${spring.data ...

  9. SpringBoot 集成 Spring Data Mongodb 操作 MongoDB 详解

    一.MongoDB 简介 MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,且与关系数据库的最为相像的.它支持的数据结构非常松散,是类似 json 的 bso ...

最新文章

  1. R语言使用dplyr包使用group_by函数、summarise函数和mutate函数计算分组下的均值、标准差、样本个数、以及分组均值的95%执行区间对应的下限值和上限值(Calculate CI)
  2. python判断对象是否有属性
  3. WF4 持久化 第四篇
  4. ML之GB:GB算法相关论文、相关思路、关键步骤、代码实现、配图集合、案例应用之详细攻略
  5. ExtJs FormPanel布局
  6. SQL基础【三、Select】
  7. Springboot Gitlab Jenkins Maven Docker 持续集成/持续交付
  8. c语言判断一个已知的二叉树是否是二叉排序树_10584 二叉树怎样序列化才能重建...
  9. 火狐查cookie_Firefox 65默认会阻止跟踪Cookie
  10. java内存模型按照线程隔离性_深入理解Java多线程与并发框(第③篇)——Java内存模型与原子性、可见性、有序性...
  11. redis源码剖析(十四)—— dump.rdb文件分析工具
  12. 2021年校招软件测试工程师经典面试题,月薪15K你需要掌握哪些知识点?
  13. Ubuntu-创建wifi热点-Android能连接(2)
  14. 社区实施 GPL 的原则介绍
  15. AIM Tech Round 5 (rated, Div. 1 + Div. 2)
  16. Namespace名称空间
  17. “The file being opened for reading does not exist“-HyperMesh
  18. 如何将图片变成png格式?怎样在线转图片格式?
  19. vs2017 c++工程编译解析
  20. Windows Server 中 DNS 服务器的新增功能

热门文章

  1. sqlserver建库建表建约束,删库删表删约束的示例总结
  2. springboot项目不加端口号也可以访问项目的方法
  3. java实现打印倒直角三角形
  4. python中seaborn画swarm图_Python可视化 | Seaborn5分钟入门(四)——stripplot和swarmplot
  5. 基于脚手架创建react项目
  6. fluent design_Fluent Design单选按钮,复选框,选择框,Java菜单
  7. ibm liberty_使用Eclipse和Open Liberty的Java EE 8上的Java 9
  8. java登录界面命令_Java命令行界面(第10部分):picocli
  9. apache.camel_Apache Camel 2.19发布–新增功能
  10. javafx窗体程序_JavaFX实际应用程序:SkedPal