Ce dont vous avez besoin est le $redact
opérateur dans le cadre d'agrégation qui vous permet de traiter la condition logique ci-dessus avec le $cond
et utilise les opérations spéciales $$KEEP
pour "conserver" le document où la condition logique est vraie ou $$PRUNE
pour "supprimer" le document où la condition était fausse.
Cette opération est similaire à avoir un $project
pipeline qui sélectionne les champs de la collection et crée un nouveau champ contenant le résultat de la requête de condition logique, puis un $match
, sauf que $redact
utilise une seule étape de pipeline qui est plus efficace.
Considérez l'exemple suivant qui illustre le concept ci-dessus :
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Puisqu'il n'y a aucun support pour le $redact
opérateur pour le moment
(au moment de la rédaction), une solution de contournement consistera à implémenter une AggregationOperation
interface qui encapsule l'opération d'agrégation avec une classe à prendre dans un 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 vous pouvez ensuite utiliser dans 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);
--MISE À JOUR--
Suivi des commentaires, pour vérifier les valeurs nulles ou nulles sur le Number2
champ dans la division, vous devrez imbriquer un $cond
expression avec la logique à la place.
L'exemple suivant suppose que vous avez une valeur d'espace réservé de 1 si soit Number2
n'existe pas/est nul ou a une valeur de zéro :
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"
]
}
}
])
Agrégation de données Spring équivalente (non testée)
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"
)
)
)
)
);