Что вам нужно, это $redact
оператор в рамках агрегации, которая позволяет proccess вышеупомянутую логическое условие с оператором в $cond
и использует специальные операции $$KEEP
«держать» документ, в котором логическое условие true или $$PRUNE
«удалить» документ, в котором условие было ложным.
Эта операция аналогична имеющей $project
трубопровод, который выбирает поля в коллекции и создает новое поле, который содержит результат логического состояния запроса, а затем последующей $match
, за исключением того, что $redact
использования который является более эффективным.
Рассмотрим следующий пример, который продемонстрировать выше концепцию:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$gte": [
{ "$divide": ["$Number1", "$Number2"] },
CONSTANT_VAR
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Поскольку существует no support for the $redact
operator yet (на момент написания), обходной путь будет реализовать AggregationOperation
интерфейс, который оборачивает операцию агрегации с класс взять в 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);
}
}
, которые затем можно использовать в 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--
Последующие меры с комментариями, чтобы проверить наличие нулей или нулевых значений на Number2
поле в подразделении, вы бы гнездиться a $cond
выражение с логикой вместо.
В следующем примере предполагается, что у вас есть значение замещающий 1, если либо Number2
не существует/равна нулю или имеет нулевое значение:
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"
]
}
}
])
Эквивалент Spring Data Aggregation (непроверенные)
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"
)
)
)
)
);
'' $ cond "' должен быть массивом, а не '' $ cond ", новый BasicDBObject() .append (" $ или ", Arrays.asList (', заменить эту строку '' $ cond " , Arrays.asList (новый BasicDBObject() .append («$ or», Arrays.asList (' – chridam
@chridam, я думаю, есть также несколько проблем с операторами $ eq. – Tolledo
Да, и это тоже. Там, где есть структура массива, вам нужно использовать соответствующую структуру данных, то есть вместо 'new BasicDBObject()' для массивов, обернуть данные с помощью 'Arrays.asList()'. – chridam