Wat je nodig hebt is de $redact
operator in het aggregatieraamwerk waarmee u de bovenstaande logische voorwaarde kunt verwerken met de $cond
operator en gebruikt de speciale bewerkingen $$ BEHOUD
om het document te "bewaren" waar de logische voorwaarde waar is of $$PRUNE
om het document te "verwijderen" waarin de voorwaarde onwaar was.
Deze bewerking is vergelijkbaar met het hebben van een $project
pijplijn die de velden in de verzameling selecteert en een nieuw veld maakt dat het resultaat van de logische voorwaardequery bevat en vervolgens een daaropvolgende $match
, behalve dat $redact
gebruikt een enkele pijplijnfase die efficiënter is.
Beschouw het volgende voorbeeld dat het bovenstaande concept demonstreert:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Aangezien er geen ondersteuning is voor de $redact
operator nog
(op het moment van schrijven) is een tijdelijke oplossing het implementeren van een AggregationOperation
interface die de aggregatiebewerking omhult met een klasse om een DBObject
in te nemen :
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);
}
}
die u vervolgens kunt gebruiken in 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);
--UPDATE--
Follow-up van de opmerkingen, om te controleren op nulls of nulwaarden op de Number2
veld in de divisie, zou je een $cond
uitdrukking met de logica in plaats daarvan.
In het volgende voorbeeld wordt ervan uitgegaan dat u een tijdelijke aanduiding heeft van 1 als Nummer2
bestaat niet/is null of heeft een waarde van nul:
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"
]
}
}
])
Equivalente Spring Data Aggregation (niet getest)
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"
)
)
)
)
);