Categories
Development MongoDB

Spring Data – MongoDB – Aggregation how to project all fields of grouped reference document

I have 2 documents, Topic and comment. Each topic has many comments and the documents look like this:

@Document
public class Topic {
    @Id
    private String id;

    @Indexed(unique = true)
    @NotBlank
    private String title;
}


@Document
public class Comment {

    @NotBlank
    private String text;

    @Indexed
    @NotBlank
    private String topic;  // id of topic

    @CreatedDate
    @Indexed
    private LocalDateTime createdDate;
}

So I actually save the id reference of Topic within comments.

This is my aggregation scenario: List the topics, which received most comments today. So three things:

  • Get all comments of today (MatchOperation)
  • Group by topic and sum comments (GroupOperation)
  • Sort by this sum (SortOperation)

This is the code so far:

MatchOperation filterCreatedDate = match(Criteria.where("createdDate").gte(today.atStartOfDay()).lt(today.plusDays(1).atStartOfDay()));
GroupOperation groupByTopic = group("topic").count().as("todaysCommentsCount");
SortOperation sortByTodaysCommentsCount = sort(Sort.Direction.DESC, "todaysCommentsCount");

Aggregation aggregation = newAggregation(filterCreatedDate, groupByTopic, sortByTodaysCommentsCount);
AggregationResults<TopTopic> result = mongoTemplate.aggregate(aggregation, Comment.class, TopTopic.class);

This is a special Class for this output:

public class TopTopic {
    private int todaysCommentsCount;
}

And this is the output of my aggregation where there is only one topic:

{
    "mappedResults": [
        {
            "todaysCommentsCount": 3
        }
    ],
    "rawResults": {
        "results": [
            {
                "_id": "5dbdca8112a617031728c417",     // topic id
                "todaysCommentsCount": 3
            }
        ],
        "ok": 1.0
    },
    "serverUsed": null,
    "uniqueMappedResult": {
        "todaysCommentsCount": 1
    }
}

I thought I am actually pretty close, but somehow it works only when I have only one topic. When there are comments from more than one topic which should then create multiple groups, I get this error:

Could not write JSON: Expected unique result or null, but got more than one!; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Expected unique result or null, but got more than one! (through reference chain: org.springframework.data.mongodb.core.aggregation.AggregationResults[\"uniqueMappedResult\"]

.. althought i do not call any getUniqueMappedResult method.

What do I do wrong?

Secondly, how can I get rid of my output class TopTopic, and instead return the original Topic values extended with todaysCommentsCount, without creating a special output class?

I appreciate for any help.

Leave an answer

Your email address will not be published. Required fields are marked *