首页 > 解决方案 > MongoTemplate 聚合未映射结果

问题描述

我正在尝试使用MongoTemplate聚合框架在 Spring Boot 项目中运行聚合管道。

我的查询毫无例外地执行。但是当我尝试调用实例getMappedResults()AggregationResults,它总是给我一个空列表。但是,如果我在调试器中检查结果,我可以看到该getRawResults()方法返回了值。

我正在使用spring-boot版本1.5.9.RELEASEspring-boot-starter-data-mongodb版本2.1.2.RELEASE

我不确定我做错了什么。


以下是聚合的代码

    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'

标签: mongodbspring-bootspring-dataspring-mongodb

解决方案


我也在努力解决聚合而不是映射复合 ID 的问题,结果我误解了映射的工作原理。(我建议阅读有关映射的 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;
        }
    }

推荐阅读