Использование оператора $cond с Spring-data-mongodb

Я хочу агрегировать следующие данные

{
   "user": "user1",
   "error": true 
}
{
   "user": "user2",
   "error": false
}
{
   "user": "user1",
   "error": false
}

В

{
     "_id": "user1",
     "errorCount": 1,
     "totalCount": 2
},
{
     "_id": "user2",
     "errorCount": 0,
     "totalCount": 1
}

С оператором $cond этого можно добиться, используя:

$group: {
    _id: "$user",
    errorCount : { "$sum" : {"$cond" : ["$error", 1, 0]}},
    totalCount : { "$sum" : 1 }
}

Однако, поскольку я использую Spring-data-mongodb, который еще не поддерживает $cond (начиная с 1.3.4-RELEASE), я не мог этого сделать.

Есть ли способ сделать ту же агрегацию без $cond?


person ltfishie    schedule 25.02.2014    source источник


Ответы (2)


Вы не связаны с этим, даже если в данных Spring еще нет «функционального интерфейса». (Кстати, поднимите JIRA)

Просто получите нативную форму и используйте типы BasicDBObject в конвейере. Итак, в принципе:

    DBCollection myCollection = mongoOperation.getCollection("collection");

    <result cast> = myCollection.aggregate(<pipeline here>);

Данные Spring дают вам абстракции, но они не запрещают использование нативных функций драйвера. На самом деле это предоставляет вам средства доступа для их использования, как я продемонстрировал выше.

person Neil Lunn    schedule 25.02.2014
comment
Да, в этом случае использование собственного интерфейса было бы намного проще. Я надеялся, что есть способ привести логическое значение непосредственно к целому числу. - person ltfishie; 26.02.2014
comment
@ltfishie В операторах агрегации нет операторов приведения. Единственным исключением является $substr, который будет приводить целые числа в виде строк. Тест $cond является допустимым способом сделать это в этом случае. - person Neil Lunn; 26.02.2014

Благодаря предложению Нила Ланна мне удалось заставить $cond использовать поддержку агрегации из spring-data. Для этого вам нужно реализовать интерфейс AggregationOperation для приема DBObject.

public class DBObjectAggregationOperation implements AggregationOperation {
  private DBObject operation;

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

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

Тогда вы сможете использовать его в TypeAggregation как обычно:

DBObject operation = (DBObject)JSON.parse ("your pipleline here...");
TypedAggregation<UserStats> aggregation = newAggregation(User.class,
    new DBObjectAggregationOperation(operation)
    );
AggregationResults<UserStats> result = mongoTemplate.aggregate(aggregation, UserStats.class); 

Этот подход позволит вам использовать любой оператор агрегации, еще не определенный во фреймворке. Однако он также не прошел проверку, установленную spring-data, и его следует использовать с осторожностью.
Пожалуйста, проголосуйте, если вы хотите, чтобы оператор $cond правильно поддерживался через фреймворк: https://jira.springsource.org/browse/DATAMONGO-861

person ltfishie    schedule 26.02.2014