Det du har brug for er $redact
operatør i aggregeringsrammen, som giver dig mulighed for at behandle ovenstående logiske tilstand med $cond
operatør og bruger de særlige operationer $$KEEP
at "beholde" dokumentet, hvor den logiske betingelse er sand eller $$PRUNE
for at "fjerne" dokumentet, hvor betingelsen var falsk.
Denne handling ligner at have en $project
pipeline, der vælger felterne i samlingen og opretter et nyt felt, der indeholder resultatet fra den logiske betingelsesforespørgsel og derefter en efterfølgende $match
, bortset fra at $redact
bruger et enkelt pipeline-trin, som er mere effektivt.
Overvej følgende eksempel, som demonstrerer ovenstående koncept:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Da der er ingen understøttelse af $redact
operatør endnu
(i skrivende stund) vil en løsning være at implementere en AggregationOperation
grænseflade, der omslutter aggregeringsoperationen med en klasse for at tage et DBObject
ind :
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);
}
}
som du så kan bruge i 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);
--OPDATERING--
Opfølgning fra kommentarerne for at kontrollere for nul- eller nulværdier på Number2
felt i divisionen, skal du indlejre en $cond
udtryk med logikken i stedet.
Det følgende eksempel antager, at du har en pladsholderværdi på 1, hvis enten Number2
eksisterer ikke/er null eller har en værdi på 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"
]
}
}
])
Tilsvarende forårsdataaggregation (ikke-testet)
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"
)
)
)
)
);