spring-data-mongodb-1.9.x中Aggregation关于Conditional Aggregation Operators的坑
来源:互联网 发布:淘宝账户名怎么修改 编辑:程序博客网 时间:2024/06/05 17:34
spring-data-mongodb-1.9.x中Aggregation关于Conditional Aggregation Operators的坑
截止至发布该文章前,spring-data-mongodb稳定版本还是1.9.x,本文中所提到的坑主要针对1.9.x或之前的版本,2.0.x版本的可以忽略本篇文章或直接浏览本文最后说明内容。
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和,分组等),并返回计算后的数据结果。有点类似sql语句中的 count(*),group by。MongoDB中通过在aggregate方法中添加一系列管道(pipeline)来达到数据处理的目的。(关于MongoDB aggregate的详细介绍、语法、使用说明等这里不做具体说明,大家自己查阅其他资料进行了解。)
Aggregate 中有一种操作方式是Conditional Aggregation Operators,先看看官方文档中的说明$cond (aggregation):
$cond (aggregation)Evaluates a boolean expression to return one of the two specified return expressions.The $cond expression has one of two syntaxes:New in version 2.6.{ $cond: { if: <boolean-expression>, then: <true-case>, else: <false-case-> } }Or:{ $cond: [ <boolean-expression>, <true-case>, <false-case> ] }If the <boolean-expression> evaluates to true, then $cond evaluates and returns the value of the <true-case> expression. Otherwise, $cond evaluates and returns the value of the <false-case> expression.The arguments can be any valid expression. For more information on expressions, see Expressions.
翻译成java语法就是一个简单的三目运算符:
<boolean-expression>?<true-case>:<false-case->
再来看看官网上的例子还是上面那地址:
ExampleThe following example use a inventory collection with the following documents:{ "_id" : 1, "item" : "abc1", qty: 300 }{ "_id" : 2, "item" : "abc2", qty: 200 }{ "_id" : 3, "item" : "xyz1", qty: 250 }The following aggregation operation uses the $cond expression to set the discount value to 30 if qty value is greater than or equal to 250 and to 20 if qty value is less than 250:db.inventory.aggregate( [ { $project: { item: 1, discount: { $cond: { if: { $gte: [ "$qty", 250 ] }, then: 30, else: 20 } } } } ])The operation returns the following results:{ "_id" : 1, "item" : "abc1", "discount" : 30 }{ "_id" : 2, "item" : "abc2", "discount" : 20 }{ "_id" : 3, "item" : "xyz1", "discount" : 30 }The following operation uses the array syntax of the $cond expression and returns the same results:db.inventory.aggregate( [ { $project: { item: 1, discount: { $cond: [ { $gte: [ "$qty", 250 ] }, 30, 20 ] } } } ])
例子很简单,通过$cond表达式,将qty值大于等于250的记录的discount值设为30,qty值小于250的记录的discount值设为20。
要实现上面的效果,在spring-data-mongodb中该怎么操作呢?
很遗憾,在spring-data-mongodb 1.9.x 的Reference 文档中并没有找到Conditional Aggregation Operators相关的例子,那就只能通过API中内容来找到想要的内容了。
在org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder
类中发现了这个一个方法:
public ProjectionOperation.ProjectionOperationBuilder project(String operation, Object... values)Adds a generic projection for the current field.Parameters:operation - the operation key, e.g. $add.values - the values to be set for the projection operation.Returns:
那就试试这个方法吧,还是采用上面这个例子(代码片段,无法执行):
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;Aggregation agg = newAggregation( project("item").and("qty").project("cond", 30, 20).as("discount") //project("item").and("qty").project("cond", "qty >= 250", 30, 20).as("discount") //project("item").and("qty >= 250").project("cond", 30, 20).as("discount") //project("item").andExpression("qty >= 250").project("cond", 30, 20).as("discount"));mongoTemplate.aggregate(agg, "collectionName", OutputType.class);
经过尝试,发现上诉四种方式都无法达到我们想要的目的(结果不对,语法错误等)。
难道就spring-data-mongodb就无法使用$cond了吗?上个大招吧!!!
首先,自己定义一个新的AggregationOperation实现类来实现spring-data-mongodb的AggregationOperation:
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;import com.mongodb.DBObject;public class DBObjectAggregationOperation implements AggregationOperation { private DBObject operation; public DBObjectAggregationOperation (DBObject operation) { this.operation = operation; } @Override public DBObject toDBObject(AggregationOperationContext context) { return context.getMappedObject(operation); }}
然后,我们就可以在代码中这样实现我们的功能:
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;/*** 通过DBObject 来创建mongodb相同的project语句* $project:* {* item: 1,* iscount:* {* $cond: [ { $gte: [ "$qty", 250 ] }, 30, *20 ]* }* }*/DBObject operation = (DBObject) new BasicDBObject("$project", new BasicDBObject("discount", new BasicDBObject("$cond", new Object[] { new BasicDBObject("$gte", new Object[] { "$qty",250 }), 30, 20 }).append("item", 1)));Aggregation agg = newAggregation( new DBObjectAggregationOperation(operation));mongoTemplate.aggregate(agg, "collectionName", OutputType.class);
经过测试,上诉代码能得到我们想要的结果。
mongodb的操作命令语法都是采用json(bson)格式,在处理复杂的命令时都可以通过类似上诉方法通过DBObject组装命令,然后通过spring-data-mongodb来执行得到相应的结果。
说明1:
在spring-data-mongodb 2.0.x 的Reference的文档中已经可以找到ConditionalOperator相关例子了Aggregation Framework Example 7:
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;TypedAggregation<InventoryItem> agg = newAggregation(InventoryItem.class, project("item").and("discount") .applyCondition(ConditionalOperator.newBuilder().when(Criteria.where("qty").gte(250)) .then(30) .otherwise(20)) .and(ifNull("description", "Unspecified")).as("description"));AggregationResults<InventoryItemProjection> result = mongoTemplate.aggregate(agg, "inventory", InventoryItemProjection.class);List<InventoryItemProjection> stateStatsList = result.getMappedResults();
github的代码中也找了相关实现类ConditionalOperator,
org.springframework.data.mongodb.core.aggregation.ConditionalOperator
后续可以通过上述例子中的代码来实现MongoDB官网的例子。
- spring-data-mongodb-1.9.x中Aggregation关于Conditional Aggregation Operators的坑
- Spring Data MongoDB 六:进阶Aggregation操作(上)
- Spring Data MongoDB七:进阶Aggregation操作(下)
- Spring Data MongoDB 六:进阶Aggregation操作(上)
- Spring Data MongoDB七:进阶Aggregation操作(下)
- Spring Data MongoDB 六:进阶Aggregation操作(上)
- Spring Data MongoDB七:进阶Aggregation操作(下)
- spring-data-mongo 实现aggregation
- 使用MongoDB中Aggregation统计数据
- mongodb中的aggregation的使用
- Aggregation
- MongoDB中强大的统计框架Aggregation使用实例解析
- MongoDB Aggregation, mongoDB的聚合操作
- mongodb aggregation在mongoengine的实现
- MongoDB Aggregation 聚合管道(Aggregation Pipeline)
- Mongodb Aggregation Framework
- mongodb aggregation 聚合
- MongoDB Aggregation Pipeline
- 12Spring的事务处理二
- java算法4~交换两个整数,不能使用任何额外的变量
- PHP 用户提交的数据的安全性验证
- python中is和==的区别
- 13Spring的数据访问方式
- spring-data-mongodb-1.9.x中Aggregation关于Conditional Aggregation Operators的坑
- IOS Label下划线 中划线
- 重叠I/O之事件通知
- 日期和数量 根据数量合并分组
- bzoj 2761
- tensorflow存储图和训练的权重为.pb,然后读取.pb并使用
- rsync for windows 详细使用教程
- Android Notification的完整例子--设置下班闹钟和护眼闹钟
- 代理总结