Spring Data – Mongo – 聚合
SpringData – Mongo – Aggregation
我与 MongoDB 和 Spring 数据的聚合框架斗争了很长一段时间,我实际上想知道我想做的事情是否真的可行。
我有以下 Mongo 个文件:
{
"_id": ObjectId("564520fad4c64dd36fb1f0a4"),
"_class": "com.sample.Purchase",
"created": new Date(1447371002645),
"productId": NumberLong(12),
"clientId": "c1",
"price": NumberLong(20)
}
我想创建以下统计数据:
List<ClientStatsEntry> entries;
public class ClientStatsEntry {
private String clientId;
private Date firstSeen;
private Date lastSeen;
private Long totalPriceSpend;
private long totalCount;
}
所以基本上步骤是:
- 按 productId 过滤集合(匹配)
- 按 clientIds (groupBy) 拆分所有剩余元素
- 检索第一个和最后一个条目的创建日期
- 汇总所有价格并存储在"totalPrice"
中
- 计算所有购买并将其存储在"totalCount"
中
我试图从这种方法开始,但我找不到一种方法可以在一个聚合管道中完成所有事情:
Aggregation agg = newAggregation(
match(Criteria.where("productId").is(productId)),
group("clientId").sum("price").as("totalPriceSpend"),
Aggregation.project("totalPriceSpend", "productId").and("productId").previousOperation());
我相信您正在寻找这个聚合管道(注释表示概述的步骤):
db.purchase.aggregate([
/* 1. Filter collection by productId (match) */
{
"$match": {
"productId": productId
}
},
/* 2. Split all remaining elements by clientIds (groupBy) */
{
"$group": {
"_id": "$clientId",
"firstSeen": { "$min": "$createdDate"}, // 3. a) Retrieve the created date of the first entry
"lastSeen": { "$max": "$createdDate"}, // 3. b) Retrieve the created date of the last entry
/* 4. Sum up all prices and store in "totalPrice" */
"totalPriceSpend": {
"$sum": "$price"
},
/* 5. Count all purchases and store it in "totalCount" */
"totalCount": {
"$sum": 1
}
}
}
])
Spring 数据 MongoDB 聚合等效如下:
Aggregation agg = Aggregation.newAggregation(
match(Criteria.where("productId").is(productId)),
group("clientId")
.min("createdDate").as("firstSeen")
.max("createdDate").as("lastSeen")
.sum("price").as("totalPriceSpend")
.count().as("totalCount"),
project("firstSeen", "lastSeen", "totalPriceSpend", "totalCount")
.and("clientId").previousOperation()
);
AggregationResults<ClientStatsEntry> result =
mongoTemplate.aggregate(agg, ClientStatsEntry.class);
List<ClientStatsEntry> clientStatsList = result.getMappedResults();
我与 MongoDB 和 Spring 数据的聚合框架斗争了很长一段时间,我实际上想知道我想做的事情是否真的可行。
我有以下 Mongo 个文件:
{
"_id": ObjectId("564520fad4c64dd36fb1f0a4"),
"_class": "com.sample.Purchase",
"created": new Date(1447371002645),
"productId": NumberLong(12),
"clientId": "c1",
"price": NumberLong(20)
}
我想创建以下统计数据:
List<ClientStatsEntry> entries;
public class ClientStatsEntry {
private String clientId;
private Date firstSeen;
private Date lastSeen;
private Long totalPriceSpend;
private long totalCount;
}
所以基本上步骤是:
- 按 productId 过滤集合(匹配)
- 按 clientIds (groupBy) 拆分所有剩余元素
- 检索第一个和最后一个条目的创建日期
- 汇总所有价格并存储在"totalPrice" 中
- 计算所有购买并将其存储在"totalCount" 中
我试图从这种方法开始,但我找不到一种方法可以在一个聚合管道中完成所有事情:
Aggregation agg = newAggregation(
match(Criteria.where("productId").is(productId)),
group("clientId").sum("price").as("totalPriceSpend"),
Aggregation.project("totalPriceSpend", "productId").and("productId").previousOperation());
我相信您正在寻找这个聚合管道(注释表示概述的步骤):
db.purchase.aggregate([
/* 1. Filter collection by productId (match) */
{
"$match": {
"productId": productId
}
},
/* 2. Split all remaining elements by clientIds (groupBy) */
{
"$group": {
"_id": "$clientId",
"firstSeen": { "$min": "$createdDate"}, // 3. a) Retrieve the created date of the first entry
"lastSeen": { "$max": "$createdDate"}, // 3. b) Retrieve the created date of the last entry
/* 4. Sum up all prices and store in "totalPrice" */
"totalPriceSpend": {
"$sum": "$price"
},
/* 5. Count all purchases and store it in "totalCount" */
"totalCount": {
"$sum": 1
}
}
}
])
Spring 数据 MongoDB 聚合等效如下:
Aggregation agg = Aggregation.newAggregation(
match(Criteria.where("productId").is(productId)),
group("clientId")
.min("createdDate").as("firstSeen")
.max("createdDate").as("lastSeen")
.sum("price").as("totalPriceSpend")
.count().as("totalCount"),
project("firstSeen", "lastSeen", "totalPriceSpend", "totalCount")
.and("clientId").previousOperation()
);
AggregationResults<ClientStatsEntry> result =
mongoTemplate.aggregate(agg, ClientStatsEntry.class);
List<ClientStatsEntry> clientStatsList = result.getMappedResults();