MongoTemplate聚合未映射结果

时间:2019-02-04 10:17:42

标签: mongodb spring-boot spring-data spring-mongodb

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

我的查询无任何例外地执行。但是,当我尝试在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'

2 个答案:

答案 0 :(得分:1)

我还为聚合问题而苦苦挣扎,因为它没有映射复合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;
        }
    }

答案 1 :(得分:0)

根据我的经验,GroupOperation将使用以下方案生成一系列文档:

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

在这种情况下,ProjectOperation将不会生成映射您的实体类的文档。

我建议您通过在logging.level.org.springframework.data=debug文件中添加application.properties来激活调试日志记录。这样,您可以查看将哪些请求发送到MongoDB并在MongoShell中重现它们,以查看每个聚合操作的结果。

测试GroupOperation结果导致实体类未正确映射的假设的一种快速方法是添加Setters并删除第二个Constructorcounttimestamp属性应该正确映射,并且Res对象只能使用counttimestamp属性创建。

注意From this post,聚合需要使用游标,因为Mongo 3.6和MongoDB 3.6需要spring 1.5.10.RELEASE进行聚合操作。考虑将Spring-boot升级到1.5.10以跳过光标。