按字段分组,排序并获得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();
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...