我有一个包含2个数字字段的文档集合,我需要根据计算的条件过滤所有文档:
Number1/Number2 >= CONST%
如何使用Spring Data Mongo和Aggregation创建这个?
我尝试过以下代码:
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:$或” 你能帮忙解决这个问题吗?
答案 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"
]
}
}
])