Результаты агрегации не могут правильно отображаться на объект Java - PullRequest
0 голосов
/ 15 июня 2019

Я пытаюсь получить данные о расписании от 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 равно нулю.

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

Но когда я вызвал getRawSchedules, который использовал getRawResults, он выглядит правильно.

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

Понятия не имею, почему он так работает.

1 Ответ

0 голосов
/ 15 июня 2019

Я не нашел никакой информации об этой проблеме в документации и здесь. Но у меня есть решение. Вы можете просто переименовать поле с _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;
}
...