【问题标题】:Aggregation results cannot properly map to Java object聚合结果无法正确映射到 Java 对象
【发布时间】:2019-10-29 19:00:02
【问题描述】:

我正在尝试从 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"
            ]
        }
    ]
}

我不知道为什么会这样。

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      相关资源
      最近更新 更多