这是我的代码(Spring 数据):
MatchOperation matchOperation = Aggregation.match(new Criteria("stats.channelId").is(channelId));
UnwindOperation unwindOperation = Aggregation.unwind("stats");
GroupOperation groupOperation = Aggregation.group("id", "discordId")
.push("stats").as("stats");
AggregationOperation addFields = (AggregationOperationContext aggregationOperationContext) -> {
DBObject dbObject =
new BasicDBObject("allGamesOnChannel",
new BasicDBObject("$sum", "$stats.pickupsPlayed"));
return new BasicDBObject("$addFields", dbObject);
};
SortOperation sortOperation = Aggregation.sort(new Sort(Sort.Direction.DESC, "allGamesOnChannel"));
LimitOperation limitOperation = Aggregation.limit(maxElements);
ProjectionOperation projectionOperation = Aggregation.project("id", "discordId", "stats");
Aggregation aggregation = Aggregation.newAggregation(matchOperation,unwindOperation, matchOperation,groupOperation,addFields,
sortOperation,limitOperation,projectionOperation);
AggregationResults<UserSummaryChannel> userSummaries = mongoTemplate.aggregate(aggregation, "pickupUser", UserSummaryChannel.class);
我在执行上面时遇到此异常:
Caused by: java.lang.IllegalArgumentException: Invalid reference 'allGamesOnChannel'!
at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:99) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:80) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.aggregation.SortOperation.toDBObject(SortOperation.java:73) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDBObject(AggregationOperationRenderer.java:56) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:580) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.MongoTemplate$BatchAggregationLoader.prepareAggregationCommand(MongoTemplate.java:2603) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.MongoTemplate$BatchAggregationLoader.aggregate(MongoTemplate.java:2585) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1570) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1511) ~[spring-data-mongodb-1.10.10.RELEASE.jar:na]
执行聚合而不分组:
Aggregation aggregation = Aggregation.newAggregation(matchOperation,addFields,
sortOperation,limitOperation,projectionOperation);
没有给出错误,所以我认为分组存在一些问题。有什么想法我在这里做错了吗?另外我想做的是过滤嵌入元素的列表,计算这些元素的属性之一的总和并基于它进行排序。也许有类似的方法可以做到这一点?
编辑 这是我的文件:
@Document
public class PickupUser {
@Id
private String id;
private String discordId;
private List<UserModeStats> stats;
private String name;
}
嵌入对象:
@Data
@EqualsAndHashCode(exclude = {"pickupsPlayed", "caps"})
public class UserModeStats {
public UserModeStats() {}
private String mode;
private String channelId;
private Long pickupsPlayed;
private Long caps;
}
我想创建的输出文档:
@Data
public class UserSummaryChannel {
public UserSummaryChannel() {}
private String id;
private String discordId;
private List<UserModeStats> stats;
//private Long allGamesOnChannel;
}
我不想包含
allGamesOnChannel
的 UserSummaryChannel
属性(无论有没有该字段,聚合都不起作用)。
这不是一个真正的解决方案,而是找到了另一种方法来实现我的目标。我自己“实现”了排序操作,以便安装此操作:
SortOperation sortOperation = Aggregation.sort(new Sort(Sort.Direction.DESC, "allGamesOnChannel"));
现在我有这个:
AggregationOperation sortOperation2 = (AggregationOperationContext aggregationOperationContext) -> {
DBObject dbObject =
new BasicDBObject("allGamesOnChannel", 1);
return new BasicDBObject("$sort", dbObject);
};
其余聚合操作保持不变。没有抛出任何异常。
分裂!
您遇到的问题是因为您没有将 allGamesOnChannel 包含在投影步骤内。
您需要将其添加到
ProjectionOperation projectionOperation = Aggregation.project("id", "discordId", "stats", "allGamesOnChannel");
我遇到了你所描述的同样的问题,这就是我解决它的方法。