0

Я использую mongoTemplate для запроса моей базы данных mongodb, и я хочу сделать подсчет в моих коллекциях. Я хочу группировать по id и включать подсчет с условиями. Я использовал этот запрос в mongoshellГруппировка и сумма с условиями

db.scenarios.aggregate([ 
    { $match: { bid: "build_1481711758" } }, 
    { 
     $group: { 
      _id: "$bid", 
      nb: { $sum: 1 }, 
      nbS: { 
       "$sum": { 
        "$cond": [ 
         { "$eq": ["$scst", true ] }, 
         1, 0 
        ] 
       } 
      }, 
      nbE: { 
       "$sum": { 
        "$cond": [ 
         { "$eq": ["$scst", false ] }, 
         1, 0 
        ] 
       } 
      } 
     } 
    } 
]) 

и возвращает то, что я хочу, но я не знаю, как преобразовать его в Java mongotemplate.

Пожалуйста, помогите :)

ответ

1

Вы можете упростить трубопровод в

db.scenarios.aggregate([ 
    { $match: { bid: "build_1481711758" } }, 
    { 
     $group: { 
      _id: "$bid", 
      nb: { $sum: 1 }, 
      nbS: { 
       "$sum": { 
        "$cond": [ "$scst", 1, 0 ] 
       } 
      }, 
      nbE: { 
       "$sum": { 
        "$cond": [ "$scst", 0, 1 ] 
       } 
      } 
     } 
    } 
]) 

Поскольку оператор $cond оценивает логическое выражение возвращает один из двух указанных возвратных выражений и scst поля по умолчанию возвращает логическое значение.

При использовании текущей версии Spring Data, который имеет поддержку $cond оператора через $project трубопровода, то это может быть превращено в (непроверенные):

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; 
import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.*; 
import org.springframework.data.mongodb.core.query.Criteria; 

Cond operatorNbS = ConditionalOperators.when("scst").thenValueOf(1).otherwise(0); 
Cond operatorNbE = ConditionalOperators.when("scst").thenValueOf(0).otherwise(1); 

Aggregation agg = newAggregation(
    match(Criteria.where("bid").is("build_1481711758"), 
    project("bid") 
     .and("scst")        
     .applyCondition(operatorNbE, field("nbE")) 
     .applyCondition(operatorNbS, field("nbS")) 
    group("bid") 
     .count().as("nb") 
     .sum("nbE").as("nbS") 
     .sum("nbE").as("nbE") 
); 
AggregationResults<Scenarios> results = mongoTemplate.aggregate(agg, Scenarios.class); 
List<Scenarios> scenarios = results.getMappedResults(); 

Если весна Версия данных не поддерживает этого, обходным путем является использование интерфейса AggregationOperation для ввода DBObject:

public class CustomGroupOperation implements AggregationOperation { 
    private DBObject operation; 

    public CustomGroupOperation (DBObject operation) { 
     this.operation = operation; 
    } 

    @Override 
    public DBObject toDBObject(AggregationOperationContext context) { 
     return context.getMappedObject(operation); 
    } 
} 

Затем осуществить $group операцию как DBObject в трубопроводе агрегации, который так же, как тот, у вас есть:

DBObject operation = (DBObject)new BasicDBObject(
    "$group", new BasicDBObject(
     "_id", "$bid" 
    ) 
    .append("nb", new BasicDBObject("$sum", 1)) 
    .append(
     "nbS", new BasicDBObject(
      "$sum", new BasicDBObject(
       "$cond", new Object[]{ "$scst", 1, 0 } 
      ) 
     ) 
    ).append(
     "nbE", new BasicDBObject(
      "$sum", new BasicDBObject(
       "$cond", new Object[]{ "$scst", 0, 1 } 
      ) 
     ) 
    ) 
); 

, которые затем можно использовать в качестве:

Aggregation agg = newAggregation(
    match(Criteria.where("bid").is("build_1481711758"), 
    new CustomGroupOperation(operation) 
); 

Для более гибкого и лучшего подхода к работе, который выполняется намного быстрее, чем выше, рассмотрите возможность запуска альтернативного а именно:

db.scenarios.aggregate([ 
    { $match: { bid: "build_1481711758" } }, 
    { 
     "$group": { 
      "_id": { 
       "bid": "$bid", 
       "scst": "$scst" 
      }, 
      "count": { "$sum": 1 } 
     } 
    }, 
    { 
     "$group": { 
      "_id": "$_id.bid", 
      "counts": { 
       "$push": { 
        "scst": "$_id.scst", 
        "count": "$count" 
       } 
      } 
     } 
    } 
])