Was Sie brauchen, ist der $redact
-Operator im Aggregations-Framework, mit dem Sie die obige logische Bedingung mit dem $cond
-Operator und verwendet die speziellen Operationen $$ BEHALTEN
um das Dokument zu "behalten", wo die logische Bedingung wahr ist, oder $$PRUNE
um das Dokument zu "entfernen", bei dem die Bedingung falsch war.
Dieser Vorgang ähnelt einem <-Code>$projekt
Pipeline, die die Felder in der Sammlung auswählt und ein neues Feld erstellt, das das Ergebnis der logischen Bedingungsabfrage enthält, und dann ein nachfolgendes $match
, außer dass $redact
verwendet eine einzige Pipelinestufe, die effizienter ist.
Betrachten Sie das folgende Beispiel, das das obige Konzept demonstriert:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Da es keine Unterstützung für $redact
gibt Betreiber noch
(zum Zeitpunkt des Schreibens) besteht eine Problemumgehung darin, eine AggregationOperation
zu implementieren Schnittstelle, die den Aggregationsvorgang mit einer Klasse umschließt, um ein DBObject
aufzunehmen :
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 Sie dann in TypeAggregation
verwenden können :
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);
--AKTUALISIEREN--
Folgen Sie den Kommentaren, um nach Nullen oder Nullwerten für Number2
zu suchen Feld in der Division müssten Sie einen $cond
Ausdruck mit der Logik stattdessen.
Das folgende Beispiel geht davon aus, dass Sie einen Platzhalterwert von 1 haben, wenn entweder Number2
existiert nicht/ist null oder hat den Wert null:
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"
]
}
}
])
Äquivalente Spring Data Aggregation (ungetestet)
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"
)
)
)
)
);