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

时间:2019-06-15 11:40:21

标签: java spring mongodb spring-boot aggregation-framework

我正在尝试从mongoDb获取日程表数据。 我创建了适当的聚合,并尝试在Spring Framework中对其进行转换。

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"
            ]
        }
    ]
}

我不知道为什么它会那样工作。

1 个答案:

答案 0 :(得分:0)

我没有在文档中和此处找到有关此问题的任何信息。但是我有一个解决方案。您可以将字段从_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;
}