java - 聚合结果无法正确映射到 Java 对象

标签 java spring mongodb spring-boot aggregation-framework

我正在尝试从 mongoDb 获取时间表数据。 我创建了适当的聚合并尝试在 Spring 框架内转换它。

db.theaters.aggregate([
    { $match: { 'city_id': <someCityId>, 'theatreRooms.schedules.spectacle_id': <someSpecId> } }, 
    { $unwind: '$theatreRooms' },
    { $unwind: '$theatreRooms.schedules' },
    { $group: { _id: { name: '$name', room: '$theatreRooms.name' }, schedules: { $addToSet: '$theatreRooms.schedules.time' } } },
    { $group: { _id: '$_id.name', schedules: { $addToSet: { room: '$_id.room', schedules: '$schedules' } } } }
])

我已经创建了正确的匹配和展开操作。但我在第一组操作时遇到了问题。 看来该操作得到了很好的解释,但由于某种原因我无法正确映射 _id 对象。

这是我的代码示例:


public class TheaterProject {

    private TheaterId _id;
    private List<String> schedules;

    public TheaterId get_id() {
        return _id;
    }

    public void set_id(TheaterId _id) {
        this._id = _id;
    }

    public List<String> getSchedules() {
        return schedules;
    }

    public void setSchedules(List<String> schedules) {
        this.schedules = schedules;
    }
}
public class TheaterId {

    @Field("name")
    private String name;

    @Field("room")
    private Integer room;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getRoom() {
        return room;
    }

    public void setRoom(Integer room) {
        this.room = room;
    }
}

public Document  getRawSchedules(String cityId, String spectaclesId){
        MatchOperation match = Aggregation.match(Criteria.where("city_id").is(cityId).and("theatreRooms.schedules.spectacle_id").is(spectaclesId));
        UnwindOperation theaterUnwind = Aggregation.unwind("theatreRooms");
        UnwindOperation schedulesUnwind = Aggregation.unwind("theatreRooms.schedules");

        GroupOperation firstGroup = Aggregation.group(Fields.from(
                Fields.field("name", "name"),
                Fields.field("room", "theatreRooms.name")))
                .addToSet("theatreRooms.schedules.time").as("schedules");

        Aggregation agg = Aggregation.newAggregation(match,theaterUnwind,schedulesUnwind,firstGroup);
        Document theaters = mongoTemplate.aggregate(agg, Theater.class, TheaterProject.class).getRawResults();
        return theaters;
    }
public List<TheaterProject>  getSchedules(String cityId, String spectaclesId){
        MatchOperation match = Aggregation.match(Criteria.where("city_id").is(cityId).and("theatreRooms.schedules.spectacle_id").is(spectaclesId));
        UnwindOperation theaterUnwind = Aggregation.unwind("theatreRooms");
        UnwindOperation schedulesUnwind = Aggregation.unwind("theatreRooms.schedules");

        GroupOperation firstGroup = Aggregation.group(Fields.from(
                Fields.field("name", "name"),
                Fields.field("room", "theatreRooms.name")))
                .addToSet("theatreRooms.schedules.time").as("schedules");

        Aggregation agg = Aggregation.newAggregation(match,theaterUnwind,schedulesUnwind,firstGroup);

        List<TheaterProject> theaters = mongoTemplate.aggregate(agg, Theater.class, TheaterProject.class).getMappedResults();
        return theaters;
    }

当我调用返回映射对象的 getSchedules 方法时,_id 字段等于 null。

[
    {
        "_id": null,
        "schedules": [
            "5:15"
        ]
    },
    {
        "_id": null,
        "schedules": [
            "6:55",
            "4:35",
            "10:15"
        ]
    }
]

但是当我调用使用 getRawResults 的 getRawSchedules 时,它看起来正常。

{
    "results": [
        {
            "_id": {
                "name": "Pinokio",
                "room": 2
            },
            "schedules": [
                "5:15"
            ]
        },
        {
            "_id": {
                "name": "Roma",
                "room": 1
            },
            "schedules": [
                "6:55",
                "4:35",
                "10:15"
            ]
        }
    ]
}

我不知道为什么会这样。

最佳答案

我在文档和此处没有找到有关此问题的任何信息。但我有一个解决办法。您只需将该字段从 _id 重命名为其他名称即可。例如,theaterId。我不知道您的问题的所有要求,但您可以仅在映射级别上执行此操作。

修复映射

import org.springframework.data.mongodb.core.mapping.Field;

import java.util.List;

public class TheaterProject {

    @Field("theaterId")
    private TheaterId _id;
    private List<String> schedules;

    public TheaterId get_id() {
        return _id;
    }

    public void set_id(TheaterId _id) {
        this._id = _id;
    }

    public List<String> getSchedules() {
        return schedules;
    }

    public void setSchedules(List<String> schedules) {
        this.schedules = schedules;
    }
}

但它需要额外的投影步骤

public List<TheaterProject>  getSchedules(String cityId, String spectaclesId){
    ...

    GroupOperation firstGroup = Aggregation.group(Fields.from(
                Fields.field("name", "name"),
                Fields.field("room", "theatreRooms.name")))
                .addToSet("theatreRooms.schedules.time").as("schedules");

    ProjectionOperation projection = Aggregation.project(Fields.from(
                Fields.field("theaterId", "_id"),
                Fields.field("schedules", "schedules")));

    Aggregation agg = Aggregation.newAggregation( ... ,firstGroup, projection);

    List<TheaterProject> theaters = mongoTemplate.aggregate(agg, "collectionName", TheaterProject.class).getMappedResults();
    return theaters;
}

关于java - 聚合结果无法正确映射到 Java 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56610038/

相关文章:

ruby-on-rails - 想要将 "acts-as-taggable-on"用于 mongoid

java - 如何在多模块android项目(kotlin + java)上配置SonarQube(使用jacoco)?

java - Google App Engine 分离前端和后端

java - 我所需模式的正则表达式是什么

Java Spring boot websocket与JS通信

javascript - Mongoose 在坐标上抛出错误值

python - 如何加快 mongoengine 查询速度

java - Spring Boot 中的依赖注入(inject)

spring - Spring中何时进行构造函数注入(inject)以及何时进行参数注入(inject)

java - Spring LDAP 返回相同且不正确的 objectSid