Spring Data-MongoDB-聚合如何投影已分组的参考文档的所有字段

我有2个文档,主题和评论。每个主题都有很多评论,文档如下所示:

@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;
}

所以我实际上将Topic的ID参考保存在注释中。

这是我的汇总场景:列出今天收到最多评论的主题。所以三件事:

  • 获取今天的所有评论(MatchOperation)
  • 按主题和注释汇总(GroupOperation)
  • 按此总和排序(SortOperation)

这是到目前为止的代码:

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);

这是此输出的特殊类:

public class TopTopic {
    private int todaysCommentsCount;
}

这是我的汇总结果,其中只有一个主题:

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

我以为我实际上已经很接近了,但是以某种方式,只有当我只有一个主题时,它才能起作用。当来自多个主题的评论应创建多个组时,出现此错误:

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\"]

..尽管我不调用任何getUniqueMappedResult方法。

我该怎么办?

第二,我如何摆脱输出类TopTopic,而是返回使用todaysCommentsCount扩展的原始Topic值,而无需创建特殊的输出类?

感谢您的帮助。

laodonggua00 回答:Spring Data-MongoDB-聚合如何投影已分组的参考文档的所有字段

第一部分

您正在将website发送回给呼叫者,其中jackson正在序列化为json并在呼叫${bucket}.s3-website.${region}.amazonaws.com时失败。

将主题字段_id添加到AggregationResults,并在getUniqueMappedResult中读取映射结果。

TopTopic

您的输出看起来像

AggregationResults

第二部分

您可以将List<TopTopic> topTopics = result.getMappedResults() 变量与 [ { "_id": "5dbdca8112a617031728c417","todaysCommentsCount": 3 } ] 一起使用,以在$$ROOT阶段映射整个文档,然后再进行$first来映射合并文档($group到合并$replaceRoot$mergeObjects)。

doc添加到Topic类。

类似

todaysCommentCount

您的输出看起来像

todaysCommentsCount

更新(添加$ lookup阶段以拉入主题字段)

MatchOperation filterCreatedDate = match(Criteria.where("createdDate").gte(today.atStartOfDay()).lt(today.plusDays(1).atStartOfDay()));
GroupOperation groupByTopic = group("topic").first("$$ROOT").as("doc").count().as("todaysCommentsCount");
SortOperation sortByTodaysCommentsCount = sort(Sort.Direction.DESC,"todaysCommentsCount");
ReplaceRootOperation replaceRoot = Aggregation.replaceRoot().withValueOf(ObjectOperators.valueOf("doc").mergeWith(new Document("todaysCommentsCount","$todaysCommentsCount")));

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

List<Topic> topTopics = result.getMappedResults();
本文链接:https://www.f2er.com/3149248.html

大家都在问