Агрегация MongoTemplate не отображает результат

Я пытаюсь запустить конвейер агрегации в проекте весенней загрузки, используя MongoTemplate и структуру агрегации.

Мой запрос выполняется без каких-либо исключений. Но когда я пытаюсь вызвать getMappedResults() в экземпляре AggregationResults, он всегда дает мне пустой список. Однако, если я проверю результат в отладчике, я увижу, что метод getRawResults() возвращает значения.

Я использую spring-boot версии 1.5.9.RELEASE и spring-boot-starter-data-mongodb версии 2.1.2. .РЕЛИЗ

Я не уверен, что я делаю неправильно.


Ниже приведен код для агрегации

    GroupOperation groupOperation = Aggregation.group("field1", "field2")
            .count().as("count")
            .max("timestamp").as("timestamp");

    ProjectionOperation projectionOperation = Aggregation.project("field1", "field2", "count", "timestamp");

    DBObject cursor = new BasicDBObject(10);
    AggregationOptions aggregationOptions = Aggregation.newAggregationOptions().cursor(cursor).build();

    Aggregation aggregation = Aggregation.newAggregation(groupOperation, projectionOperation).withOptions(aggregationOptions);
    AggregationResults<Res> activities = mongoTemplate.aggregate(aggregation, "test_collection", Res.class);

Ниже приведен класс, в котором я пытаюсь отобразить результат.

public class Res {
    public String field1;

    public String field2;

    public Long timestamp;

    public Integer count;

    public Res() {
    }

    public Res(String field1, String field2, Long timestamp, Integer count) {
        this.field1 = field1;
        this.field2 = field2;
        this.timestamp = timestamp;
        this.count = count;
    }
}

Примечание. Если я пропущу курсор в AggregationOptions, я получу следующую ошибку

'The 'cursor' option is required, except for aggregate with the explain argument'

person greenPadawan    schedule 04.02.2019    source источник


Ответы (2)


Я также боролся с этой проблемой агрегации, а не сопоставления составных идентификаторов, и оказалось, что я неправильно понял, как работает сопоставление. (Я бы рекомендовал прочитать документацию Spring по сопоставлению: https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-chapter)

Также стоит отметить, что поведение сопоставления изменилось где-то между Spring Boot 2.1.8 и 2.3.4 (я столкнулся с этой проблемой только при обновлении). В версии 2.1.8 вы могли правильно или неправильно сопоставлять составные ключи с отдельными полями в одном классе Java (например, в исходном классе Res, опубликованном в вопросе).

ответ charlycou дает подсказку во фрагменте кода возвращенного документа (обратите внимание, что _id является объектом json)

    {
     _id: {
       field1:"field1",
       field2:"field2"
     },
     count: countResult,
     timestamp:timestamp
    }

Чтобы сопоставление работало правильно в этом сценарии составного ключа, создайте класс java для представления составного ключа. Например:

    public class ResId {
        public String field1;
        public String field2; 
     
        public ResId(String field1, String field2){
           this.field1 = field1;
           this.field2 = field2;
       }
    }
    
    public class Res {
        @Id
        public ResId resId;
    
        public Long timestamp;
    
        public Integer count;
    
        public Res() {
        }
    
        public Res(ResId resId, Long timestamp, Integer count) {
            this.resId = resId;
            this.timestamp = timestamp;
            this.count = count;
        }
    }
person Austen    schedule 23.09.2020

По моему опыту, в результате GroupOperation получится массив документов со следующей схемой:

{
  _id: {
    field1:"field1",
    field2:"field2"
  },
  count: countResult,
  timestamp:timestamp
}

В этом случае ProjectOperation не приведет к документам, которые отображают ваш класс сущности.

Я предлагаю вам активировать ведение журнала отладки, добавив logging.level.org.springframework.data=debug в файл application.properties. Таким образом, вы могли видеть, какие запросы отправляются в MongoDB, и воспроизводить их в MongoShell, чтобы увидеть результат каждой из ваших операций агрегирования.

Быстрый способ проверить гипотезу о том, что ваш класс сущностей неправильно сопоставлен из-за результата GroupOperation, состоит в том, чтобы добавить Setters и удалить второй Constructor. Атрибуты count и timestamp должны быть правильно сопоставлены, а объект Res будет создан только со свойствами count и timestamp.

Примечание: из этого поста для агрегации требуется курсор, поскольку для Mongo 3.6 и MongoDB 3.6 требуется spring 1.5.10.RELEASE для операций агрегации. Подумайте об обновлении Spring-boot до версии 1.5.10, чтобы пропустить курсор.

person charlycou    schedule 05.02.2019
comment
Я попробовал ваше предложение, добавил сеттеры и удалил все конструкторы, кроме конструктора по умолчанию. Тем не менее, он все еще не отображал результат. Но когда я обновился до весны 1.5.10, он начал работать. Я не уверен, что это проблема, характерная для весенней версии. - person greenPadawan; 07.02.2019
comment
Вы изменили свой ProjectOperation, как я предложил? Не уверен, что это связано с версией Spring. Тем не менее, для сборки Spring AggregationOperation лучше всего скопировать запрос MongoDB из журнала отладки и протестировать каждую операцию в MongoShell. - person charlycou; 07.02.2019
comment
Да, я изменил операцию проекта, как вы предложили, но все равно не сработало. Во всяком случае, после обновления весенней версии, похоже, работает - person greenPadawan; 08.02.2019