javascript
使用Spring Data MongoDB和Spring Boot进行数据聚合
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 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进行数据聚合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞飞资源库API接口(api接口ddos
- 下一篇: 安卓版应用汇(下载安卓应用汇)