在一次聚合 Spring 引导中动态地进行多个平均

Dynamically multiple averages in one Aggregation Spring Boot

我一直在尝试使用 Spring boot Aggregation 按标识符分组多个平均值。我想要的平均值的字段由参数给定的数组定义,但我无法检索多个平均值。 数据存储如下:

{
    "_id": {
        "$oid": "XX"
    },
    "space_id": "AA",
    "temperature": 50,
    "temperatureUoMCode": 0,
    "pm25": 50,
    "pm25UoMCode": 0,
    "co2": 0.0005,
    "co2UoMCode": 0,
    "co": 1,
    "coUoMCode": 0,
    "gas": 50,
    "gasUoMCode": 0,
    "humidity": 50,
    "humidityUoMCode": 0,
    "occupants": 6,
    "maxCapacity": 15,
    "_class": "Record"
}

我使用的代码:

List<AggregationOperation> aggregationOperations = new ArrayList<>();
        aggregationOperations.add(Aggregation.match(
                Criteria.where("space_id").is(space_id)
        ));
        for(Variable var : concerns){
            System.out.println(var.getField());
            aggregationOperations.add(Aggregation.group(
                            space_id).
                    avg(var.getField()).as(var.getAvg()));
        }
        Aggregation aggregation = Aggregation.newAggregation(
                aggregationOperations
        );
        AggregationResults<HashMap> results = mongoTemplate.aggregate(
                aggregation, "records",HashMap.class);

另外,变量class是一个枚举,有两个字段,db中的字段名(field)和平均别名(avg)。 当我 运行 它时,我得到以下输出:

co
pm25
temperature
humidity
gas
    2021-09-22 11:34:17.046 ERROR 42971 --- [a1-0b2af6e69097] TConfig$$EnhancerBySpringCGLIB$3c396b : Invalid reference 'pm25'!
    java.lang.IllegalArgumentException: Invalid reference 'pm25'!
        at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:114)
        at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:86)
        at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.getValue(GroupOperation.java:529)
        at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.toDocument(GroupOperation.java:507)
        at org.springframework.data.mongodb.core.aggregation.GroupOperation.toDocument(GroupOperation.java:441)
        at org.springframework.data.mongodb.core.aggregation.AggregationOperation.toPipelineStages(AggregationOperation.java:55)
        at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDocument(AggregationOperationRenderer.java:56)
        at org.springframework.data.mongodb.core.aggregation.AggregationPipeline.toDocuments(AggregationPipeline.java:81)
        at org.springframework.data.mongodb.core.aggregation.Aggregation.toPipeline(Aggregation.java:716)
        at org.springframework.data.mongodb.core.AggregationUtil.createPipeline(AggregationUtil.java:112)
        at org.springframework.data.mongodb.core.MongoTemplate.doAggregate(MongoTemplate.java:2144)
        at org.springframework.data.mongodb.core.MongoTemplate.doAggregate(MongoTemplate.java:2119)
        at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:2113)
        at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:2014)
        at co.edu.javeriana.smartuj.EnvironmentalAlerts.services.AlertService.makeQuery(AlertService.java:131)

如果有人遇到类似的问题,我按照 设法解决了。我意识到,与其创建各种 GroupOperations,不如创建一个并使用它来存储所有操作,方法是将“as”函数的 return 保存在同一个对象中:

 MatchOperation matchOperation = Aggregation.match(Criteria.where("space_id").is(space_id));
        GroupOperation groupOperation = null;
        for(Variable var : concerns){
            if (groupOperation == null){
                groupOperation = Aggregation.group("space_id")
                        .avg(var.getField())
                        .as(var.getAvg());
            }else
                groupOperation = groupOperation
                        .avg(var.getField())
                        .as(var.getAvg());
        }
        Aggregation aggregation = Aggregation.newAggregation(
                matchOperation,
                groupOperation
        );
        AggregationResults<HashMap> results = mongoTemplate.aggregate(
                aggregation, "records",HashMap.class);
        return results.getUniqueMappedResult();