如何在Spring-MongoDb聚合框架中使用$cond操作

11

我有一个包含类似以下项目的聚合管道:

$project: {
  start: {
    $cond: {
      if: {
        $eq: ["$start", "EARLY"]
      },
      then: "$deltastart.start",
      else: "$deltastart.end"
    }
  },...
},...

在mongo shell中,一切都很正常。如何在Spring-Mongodb中使用聚合框架表达这一点呢?我看到了ProjectionOperationBuilder、ExpressionProjectionOperationBuilder类型,但没有使用它们的示例……有什么建议吗?

2个回答

11

如果使用当前Spring Data版本并且支持通过$cond操作符的$project管道,那么可以将其转换为(未经测试):

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.*;
import org.springframework.data.mongodb.core.query.Criteria;

Cond condOperation = ConditionalOperators.when(Criteria.where("start").is("EARLY"))
                                    .thenValueOf("deltastart.start")
                                    .otherwise("deltastart.end");

Aggregation agg = newAggregation(project().and(condOperation).as("start"));
AggregationResults<MyClass> results = mongoTemplate.aggregate(agg, MyClass.class); 
List<MyClass> myList = results.getMappedResults();
对于不支持聚合操作中的$cond运算符的Spring-Data MongoDB版本,有一个解决方法是实现AggregationOperation接口以传入DBObject参数。
public class CustomProjectAggregationOperation implements AggregationOperation {
    private DBObject operation;

    public CustomProjectAggregationOperation (DBObject operation) {
        this.operation = operation;
    }

    @Override
    public DBObject toDBObject(AggregationOperationContext context) {
        return context.getMappedObject(operation);
    }
}

然后将$project操作实现为聚合管道中的DBObject,与您当前拥有的管道相同:

DBObject operation = (DBObject) new BasicDBObject(
    "$project", new BasicDBObject(
         "start", new BasicDBObject(
                "$cond", new Object[]{
                        new BasicDBObject(
                            "$eq", new Object[]{ "$start", "EARLY"}
                        ),
                        "$deltastart.start",
                        "$deltastart.end"
                 }
           )
     )
);

然后您可以在TypeAggregation中使用它:

TypedAggregation<CustomClass> aggregation = newAggregation(CustomClass.class,
    new CustomProjectAggregationOperation(operation)
);
AggregationResults<CustomClass> result = mongoTemplate.aggregate(aggregation, CustomClass.class); 

你能展示一下 DBObjectAggregationOperation 类的实现吗? - Half Blood Prince
那是一个打错了的字,应该是 CustomProjectAggregationOperation,我已经改正了。 - chridam
请问哪个Spring Data版本支持 "applyCondition" 方法? - Jagan
1
很遗憾,AggregationOperationspring-data-mongodb-2.0.8.RELEASE版本中不再公开toDBObject方法。 - Always Learning

2

我遇到了同样的问题并在Google上搜索,这是我找到的第一个结果,所以我想为将来的读者补充一下,自从1.10 RC1版本以来,这个功能现在已经可用,使用ConditionalOperators.Cond类。

您可以在这里阅读JavaDoc。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接