Java / Mongotemplate聚合,组和总和不按预期进行分组
我有一个Mongo系列,其中包含许多文档,其中包含有关给我们用户的信用 /礼物的信息。
我希望能够运行一个汇总的查询,以获取在最后X天内收到信用 /礼物的所有用户,并将每个用户的信用额度总值汇总。
我认为我有正确的汇总,组和总代码,但是每个用户都会恢复多个对象,因为我要分组,然后将值(?)总结
为我的文档是什么结构看起来像:
_id: ObjectId("61c36a8a21047124c4181271"),
transactionId: UUID("6fbf536e-7a53-442c-9615-53e32362608b"),
userId: 'xxxxx',
transactionMessage: 'Account credited with: 1',
transactionType: 'CREDIT',
transactionAction: 'GIFT',
inComingPaymentFromUserId: 'xxxx',
transactionAmount: Decimal128("1"),
customMessage: "blah'",
createdDate: ISODate("2021-12-22T18:12:26.812Z"),
lastUpdatedAt: ISODate("2021-12-22T18:12:26.812Z"),
这是我的查询代码:
@Override
public List<RecentlyRewardedUsers> findRecentlyRewardedUsers(Integer range, Pageable pageable) {
Aggregation agg = Aggregation.newAggregation(
match(Criteria.where("createdDate").gt(LocalDate.now().minusDays(range))
.andOperator(Criteria.where("transactionAction").is("GIFT"))), sort(Sort.Direction.DESC, "createdDate"),
group("userId", "_id").sum("transactionAmount").as("totalValueAwarded"),
project("userId", "totalValueAwarded"),
skip((long) pageable.getPageNumber() * pageable.getPageSize()),
limit(pageable.getPageSize()));
try {
return mongoTemplate.aggregate(agg, "Transactions", RecentlyRewardedUsers.class).getMappedResults();
} catch (Exception ex) {
throw new ServiceUnavailableException("Unable to perform Mongo Operation {" + ex.getLocalizedMessage() + "}", "User");
}
}
这也是我的映射类:
@Getter
@Setter
public class RecentlyRewardedUsers {
@Field("userId")
private String userId;
private String totalValueAwarded;
private String userDisplayName;
private String profilePicUrl;
}
就像我上面说的那样,当查询结果映射到最近的whardrewardedusers类时,我看到了同一用户ID的多个条目(请参见下图) 。我本以为应该将其全部卷起/汇总到该用户
如果有人可以阐明我做错了什么,那真是太好了!
谢谢
**编辑** 根据以下答案 用户Eskandar Abedini,我已经更新了代码以进行以下内容:
Criteria operator = new Criteria();
operator.andOperator(
Criteria.where("createdDate").gt(LocalDate.now().minusDays(2))
.andOperator(Criteria.where("transactionAction").is("GIFT")));
MatchOperation matchOperation = Aggregation.match(operator);
GroupOperation groupOperation = Aggregation.group("userId").sum("transactionAmount").as("totalValueAwarded");
List<String> sortOptions = new ArrayList<>();
sortOptions.add("createdDate");
Sort sort = new Sort(Sort.Direction.DESC, sortOptions);
SortOperation sortOperation = Aggregation.sort(sort);
Aggregation aggregation = Aggregation.newAggregation(Transaction.class, matchOperation, groupOperation, sortOperation);
AggregationResults<RecentlyRewardedUsers> aggregationResults = mongoTemplate.aggregate(aggregation, Transaction.class, RecentlyRewardedUsers.class);
当我现在执行上述错误时,我会收到此错误:
java.lang.IllegalArgumentException: Invalid reference 'createdDate'!
如果目前我删除了排序选项。代码将执行。但是,我没有将用户ID映射到我最近的读课上。
Criteria operator = new Criteria();
operator.andOperator(
Criteria.where("createdDate").gt(LocalDate.now().minusDays(2))
.andOperator(Criteria.where("transactionAction").is("GIFT")));
MatchOperation matchOperation = Aggregation.match(operator);
GroupOperation groupOperation = Aggregation.group("userId").sum("transactionAmount").as("totalValueAwarded");
Aggregation aggregation = Aggregation.newAggregation(Transaction.class, matchOperation, groupOperation);
AggregationResults<RecentlyRewardedUsers> aggregationResults = mongoTemplate.aggregate(aggregation, Transaction.class, RecentlyRewardedUsers.class);
任何帮助都会很棒。
谢谢
编辑 添加图像以显示我的意思是用UserID未被映射在MappedResponse中。但是,在查询的原始响应中,用户ID被映射到documentID _id
I have a mongo collection which has many documents containing information about credits / gifts given to our users.
I would like to be able to run an Aggregated Query to get all the users who have received a credit / gift within the last x number of days and sum the total value of those credits for each user.
I think I have the correct Aggregation, group and sum code but I'm getting back more than one object per user, which shouldn't be the case since I'm grouping and then summing the values(?)
Here is what my document structure looks like:
_id: ObjectId("61c36a8a21047124c4181271"),
transactionId: UUID("6fbf536e-7a53-442c-9615-53e32362608b"),
userId: 'xxxxx',
transactionMessage: 'Account credited with: 1',
transactionType: 'CREDIT',
transactionAction: 'GIFT',
inComingPaymentFromUserId: 'xxxx',
transactionAmount: Decimal128("1"),
customMessage: "blah'",
createdDate: ISODate("2021-12-22T18:12:26.812Z"),
lastUpdatedAt: ISODate("2021-12-22T18:12:26.812Z"),
And here is my query code:
@Override
public List<RecentlyRewardedUsers> findRecentlyRewardedUsers(Integer range, Pageable pageable) {
Aggregation agg = Aggregation.newAggregation(
match(Criteria.where("createdDate").gt(LocalDate.now().minusDays(range))
.andOperator(Criteria.where("transactionAction").is("GIFT"))), sort(Sort.Direction.DESC, "createdDate"),
group("userId", "_id").sum("transactionAmount").as("totalValueAwarded"),
project("userId", "totalValueAwarded"),
skip((long) pageable.getPageNumber() * pageable.getPageSize()),
limit(pageable.getPageSize()));
try {
return mongoTemplate.aggregate(agg, "Transactions", RecentlyRewardedUsers.class).getMappedResults();
} catch (Exception ex) {
throw new ServiceUnavailableException("Unable to perform Mongo Operation {" + ex.getLocalizedMessage() + "}", "User");
}
}
Here is also my mapped class:
@Getter
@Setter
public class RecentlyRewardedUsers {
@Field("userId")
private String userId;
private String totalValueAwarded;
private String userDisplayName;
private String profilePicUrl;
}
Like I said above, when the the results of the query are mapped to the RecentlyRewardedUsers class, I see multiple entries for the same userId (see image below). I would have thought it should be all rolled up / summed up into one entry for that userId
If anyone can shed some light on what I've done wrong that would be great!!
Thank you
** EDIT **
Based on the answer below from
user Eskandar Abedini, I've updated my code to be the following:
Criteria operator = new Criteria();
operator.andOperator(
Criteria.where("createdDate").gt(LocalDate.now().minusDays(2))
.andOperator(Criteria.where("transactionAction").is("GIFT")));
MatchOperation matchOperation = Aggregation.match(operator);
GroupOperation groupOperation = Aggregation.group("userId").sum("transactionAmount").as("totalValueAwarded");
List<String> sortOptions = new ArrayList<>();
sortOptions.add("createdDate");
Sort sort = new Sort(Sort.Direction.DESC, sortOptions);
SortOperation sortOperation = Aggregation.sort(sort);
Aggregation aggregation = Aggregation.newAggregation(Transaction.class, matchOperation, groupOperation, sortOperation);
AggregationResults<RecentlyRewardedUsers> aggregationResults = mongoTemplate.aggregate(aggregation, Transaction.class, RecentlyRewardedUsers.class);
When I now execute the above I get this error:
java.lang.IllegalArgumentException: Invalid reference 'createdDate'!
If for the moment I remove the sort options. The code will execute. However I'm not getting the userId mapped into my RecentlyRewarded class.
Criteria operator = new Criteria();
operator.andOperator(
Criteria.where("createdDate").gt(LocalDate.now().minusDays(2))
.andOperator(Criteria.where("transactionAction").is("GIFT")));
MatchOperation matchOperation = Aggregation.match(operator);
GroupOperation groupOperation = Aggregation.group("userId").sum("transactionAmount").as("totalValueAwarded");
Aggregation aggregation = Aggregation.newAggregation(Transaction.class, matchOperation, groupOperation);
AggregationResults<RecentlyRewardedUsers> aggregationResults = mongoTemplate.aggregate(aggregation, Transaction.class, RecentlyRewardedUsers.class);
Any help would be amazing.
Thank you
Edit
Adding image to show what I mean by userId not being mapped in the MappedResponse. However in the Raw response of the query the userId is getting mapped to the documentId _id
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从
组中删除
_id
group(“ userId”,“ _id”)这与您相似,其实现也很明确。
github源
Remove
_id
fromgroup("userId", "_id")
This is somehow similar to yours, its implementation is clear too.
GitHub Source