Spring Data MongoDB聚合 - 按计算值匹配

时间:2017-01-12 09:19:15

标签: mongodb mongodb-query aggregation-framework spring-data-mongodb

我有一个包含2个数字字段的文档集合,我需要根据计算的条件过滤所有文档:

Number1/Number2 >= CONST%

如何使用Spring Data Mongo和Aggregation创建这个?

- UPDATE -

我尝试过以下代码:

return new RedactAggregationOperation(
            new BasicDBObject(
                    "$redact",
                    new BasicDBObject(
                            "$cond", new BasicDBObject()
                            .append("if", new BasicDBObject(
                                    "$gte", Arrays.asList(new BasicDBObject(
                                    "$divide",
                                    Arrays.asList(
                                            "$Number1",
                                            new BasicDBObject(
                                                    "$cond",
                                                    new BasicDBObject()
                                                            .append("$or", Arrays.asList(
                                                                    new BasicDBObject(
                                                                            "$eq", new BasicDBObject(
                                                                            "$Number2", 0)),
                                                                    new BasicDBObject(
                                                                            "$eq", new BasicDBObject(
                                                                            new BasicDBObject(
                                                                                    "$ifNull",
                                                                                    new BasicDBObject(
                                                                                            "$Number2", 0)).toString(), 0))))
                                                            .append("then", 1000000)
                                                            .append("else", "$Number2")), CONSTANT_VAR))
                            )))
                            .append("then", "$$KEEP")
                            .append("else", "$$PRUNE")
                    )
            )
    );

但是有一个错误“无法识别参数$ cond:$或” 你能帮忙解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

您需要的是聚合框架中的 $redact 运算符,它允许您使用 $cond 运算符处理上述逻辑条件,使用特殊操作 $$KEEP 来"保持"逻辑条件为真的文档或 $$PRUNE 到"删除"条件错误的文件。

此操作类似于具有 $project 管道,该管道选择集合中的字段并创建一个新字段,其中包含逻辑条件查询的结果,然后是后续的 $match ,但 $redact 使用效率更高的单个管道阶段。

考虑以下展示上述概念的示例:

db.collection.aggregate([
    { 
        "$redact": {
            "$cond": [
                { 
                    "$gte": [
                        { "$divide": ["$Number1", "$Number2"] },
                        CONSTANT_VAR
                    ]
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

由于有no support for the $redact operator yet(在撰写本文时),解决方法是实现一个AggregationOperation接口,该接口将聚合操作包装在一个类中以接收{{1} }}:

DBObject

然后您可以在public class RedactAggregationOperation implements AggregationOperation { private DBObject operation; public RedactAggregationOperation (DBObject operation) { this.operation = operation; } @Override public DBObject toDBObject(AggregationOperationContext context) { return context.getMappedObject(operation); } } 中使用

TypeAggregation

<强> - UPDATE -

评论的后续行动,要检查部门中Aggregation agg = newAggregation( new RedactAggregationOperation( new BasicDBObject( "$redact", new BasicDBObject( "$cond", new BasicDBObject() .append("if", new BasicDBObject( "$gte", Arrays.asList( new BasicDBObject( "$divide", Arrays.asList( "$Number1", "$Number2" ) ), CONSTANT_VAR ) ) ) .append("then", "$$KEEP") .append("else", "$$PRUNE") ) ) ) ); AggregationResults<Example> results = mongoTemplate.aggregate( (TypedAggregation<Example>) agg, Example.class); 字段的空值或零值,您必须使用 $cond 表达式嵌套而不是逻辑。

以下示例假设如果Number2不存在/为空或值为零,则占位符值为1:

Number2

等效的Spring Data Aggregation(未经测试)

db.collection.aggregate([
    { 
        "$redact": {
            "$cond": [
                { 
                    "$gte": [
                        { 
                            "$divide": [
                                "$Number1", {
                                    "$cond": [
                                        {
                                            "$or": [
                                                { "$eq": ["$Number2", 0] },
                                                { 
                                                    "$eq": [
                                                        { "$ifNull": ["$Number2", 0] }, 0
                                                    ]
                                                }
                                            ]
                                        },
                                        1,  // placeholder value if Number2 is 0
                                        "$Number2"                                          
                                    ]
                                }
                            ] 
                        },
                        CONSTANT_VAR
                    ]
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])