Я пытаюсь создать агрегированный запрос с использованием mongotemplate, где есть группировка по дате (например, 2016-03-01) вместо datetime (например, 2016-03-01 16:40:12). Операция dateToString существует в документации mongodb, ее можно использовать для извлечения даты из даты и времени с помощью форматирования: https://docs.mongodb.org/manual/reference/operator/aggregation/ dateToString / но я заставляю его работать с mongotemplate - я получаю исключение NullPointerException. (моя версия db - 3.2)

List<AggregationOperation> aggregationOperations = new ArrayList<AggregationOperation>();

aggregationOperations.add(
          Aggregation.project("blabla", ...).
          andExpression("dateToString('%Y-%m-%d',timeCreated).as("date"));

aggregationOperations.add(Aggregation.group("date").sum("blabla").as("blabla"));

AggregationResults<?> aggregationResults = this.mongoTemplate.aggregate(
                        Aggregation.newAggregation(aggregationOperations),
                                    collectionName,
                                    resultClass);

Когда я использую dayOfMonth(timeCreated) для извлечения дня, нет никаких исключений, но я не смог найти и примера того, как это работает с dateToString. Я пробовал без "" для формата даты, и это тоже не сработало ...

Это исключение, которое я получаю:

java.lang.NullPointerException
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:226)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:194)
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:255)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:194)
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:255)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:194)
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:255)
    at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:324)
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:263)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:194)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:136)
    at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:36)
    at com.mongodb.OutMessage.putObject(OutMessage.java:289)
    at com.mongodb.OutMessage.writeQuery(OutMessage.java:211)
    at com.mongodb.OutMessage.query(OutMessage.java:86)
    at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:81)
    at com.mongodb.DB.command(DB.java:320)
    at com.mongodb.DB.command(DB.java:299)
    at com.mongodb.DB.command(DB.java:374)
    at com.mongodb.DB.command(DB.java:246)
    at org.springframework.data.mongodb.core.MongoTemplate$2.doInDB(MongoTemplate.java:357)
    at org.springframework.data.mongodb.core.MongoTemplate$2.doInDB(MongoTemplate.java:355)
    at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:442)
    at org.springframework.data.mongodb.core.MongoTemplate.executeCommand(MongoTemplate.java:355)
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1497)
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1432)

РЕДАКТИРОВАТЬ:

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

В дополнение к полю «timeCreated», которое содержит дату и время, мы сохранили еще одно поле в документе: «date», которое содержит только дату (до тех пор, пока не будет).

Например, если «timeCreated» = «2015-12-24 16: 36: 06.657 + 02: 00», то дата будет «2015-12-24 00:00:00», и мы сохраним 1449180000000. Теперь мы можем просто сгруппировать по «дате».

5
Ayelet 3 Янв 2016 в 17:57

2 ответа

Лучший ответ

Вы можете сначала попробовать спроецировать поля, используя SpEL andExpression в операции проецирования, а затем сгруппируйте по новым полям в операции группировки:

Aggregation agg = newAggregation(
    project()       
        .andExpression("year(timeCreated)").as("year")
        .andExpression("month(timeCreated)").as("month")
        .andExpression("dayOfMonth(timeCreated)").as("day"),
    group(fields().and("year").and("month").and("day"))     
        .sum("blabla").as("blabla")
);

AggregationResults<BlaBlaModel> result = 
    mongoTemplate.aggregate(agg, collectionName, BlaBlaModel.class);
List<BlaBlaModel> resultList = result.getMappedResults();
6
chridam 3 Янв 2016 в 15:10

Вы можете попробовать использовать класс DateOperators.DateToString

aggregationOperations.add(
      Aggregation.project("blabla", ...).
      and(DateOperators.DateToString.dateOf("timeCreated").toString("%Y-%m-%d"));
0
rohit 14 Фев 2019 в 15:22