O que você precisa é do
$redact
operador na estrutura de agregação que permite processar a condição lógica acima com o $cond
operador e usa as operações especiais $$KEEP
para "manter" o documento onde a condição lógica é verdadeira ou $$PRUNE
para "remover" o documento onde a condição era falsa. Esta operação é semelhante a ter um
$project
pipeline que seleciona os campos na coleção e cria um novo campo que contém o resultado da consulta de condição lógica e, em seguida, um $match
, exceto que $redact
usa um único estágio de pipeline que é mais eficiente. Considere o seguinte exemplo que demonstra o conceito acima:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Como não há não há suporte para o
$redact
operador ainda
(no momento da escrita), uma solução alternativa será implementar um AggregationOperation
interface que envolve a operação de agregação com uma classe para receber um 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);
}
}
que você pode usar em
TypeAggregation
: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);
--ATUALIZAÇÃO--
Acompanhamento dos comentários, para verificar valores nulos ou zero no
Number2
campo na divisão, você teria que aninhar um $cond
expressão com a lógica em vez disso. O exemplo a seguir pressupõe que você tenha um valor de espaço reservado de 1 se
Number2
não existe/é nulo ou tem valor zero: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"
]
}
}
])
Agregação de dados equivalente do Spring (não testada)
Aggregation agg = newAggregation(
new RedactAggregationOperation(
new BasicDBObject(
"$redact",
new BasicDBObject(
"$cond", Arrays.asList(
new BasicDBObject(
"$gte", Arrays.asList(
new BasicDBObject(
"$divide", Arrays.asList(
"$Number1",
new BasicDBObject(
"$cond", Arrays.asList(
new BasicDBObject( "$or": Arrays.asList(
new BasicDBObject("$eq", Arrays.asList("$Number2", 0)),
new BasicDBObject("$eq", Arrays.asList(
new BasicDBObject("$ifNull", Arrays.asList("$Number2", 0)), 0
)
)
)
),
1, // placeholder value if Number2 is 0
"$Number2"
)
)
)
),
CONSTANT_VAR
)
), "$$KEEP", "$$PRUNE"
)
)
)
)
);