如何解决按字段分组,排序并获得MongoDB中该组的第一个或最后一个,无论如何带有Spring Data
我有以下实体(省略了getter,setter和构造函数)
public class Event {
@Id
private String id;
private String internalUuid;
private EventType eventType;
}
EventType是一个包含任意事件类型的枚举:
public enum EventType {
ACCEPTED,PROCESSED,DELIVERED;
}
我的问题是我有一个包含很多事件的表,有些事件具有相同的internalUuid但状态不同。我需要获取事件列表,每个事件代表“最新”状态(按EventType排序即可)。目前,我只是获取所有内容,将代码中的列表分组,按EventType对列表进行排序,然后仅使用每个列表的第一个元素创建一个新列表。
示例如下。
表中的数据:
{ "id": "1","internalUuid": "1","eventType": "ACCEPTED" },{ "id": "2","eventType": "PROCESSED" },{ "id": "3","eventType": "DELIVERED" },{ "id": "4","internalUuid": "2",{ "id": "5",{ "id": "6","internalUuid": "3","eventType": "ACCEPTED" }
查询的输出(任何顺序都可以):
[
{ "id": "3","eventType": "ACCEPTED" }
]
不能保证“较高”状态也具有“较高” ID。
我如何不手工完成整个过程呢?我真的不知道如何开始,因为我是MongoDB的新手,但是在Google上找不到任何对我有帮助的东西。我正在使用Spring Boot和Spring Data。
谢谢!
解决方法
好的,我想我已经解决了(感谢Joe's评论)。我不是100%确信代码正确无误,但似乎可以满足我的要求。我愿意改进。
((我必须向Event和EventType添加一个优先级字段,因为按eventType进行排序显然会对枚举名称进行基于字符串的(字母顺序)排序):
private List<Event> findCandidates() {
// First,'match' so that all documents are found
final MatchOperation getAll = Aggregation.match(new Criteria("_id").ne(null));
// Then sort by priority
final SortOperation sort = Aggregation.sort(Sort.by(Sort.Direction.DESC,"priority"));
// After that,group by internalUuid and make sure to also push the full event to not lose it for the next step
final GroupOperation groupByUuid = Aggregation.group("internalUuid").push("$$ROOT").as("events");
// Get the first element of each sorted and grouped list (I'm not fully sure what the 'internalUuid' parameter does here and if I could change that)
final ProjectionOperation getFirst = Aggregation.project("internalUuid").and("events").arrayElementAt(0).as("event");
// We're nearly done! Only thing left to do is to map to our Event to have a usable List of Event in .getMappedResults()
final ProjectionOperation map = Aggregation.project("internalUuid")
.and("event._id").as("_id")
.and("event.internalUuid").as("internalUuid")
.and("event.eventType").as("eventType")
.and("event.priority").as("priority");
final Aggregation aggregation = Aggregation.newAggregation(getAll,sort,groupByUuid,getFirst,map);
final AggregationResults<InvoiceEvent> aggregationResults =
mongoTemplate.aggregateAndReturn(InvoiceEvent.class).by(aggregation).all();
return aggregationResults.getMappedResults();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。