You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MongoTemplate实现带分页排序的多集合统计查询

可以通过MongoTemplate实现该需求

完全可以通过MongoTemplate结合MongoDB的聚合框架来实现你需要的查询,包括用户信息关联、统计计数、分页和排序功能。以下是具体实现方案:

核心思路:使用MongoDB聚合管道

我们需要构建一个聚合管道,依次完成关联Catalog集合、统计Catalog数量、关联Item集合、统计Item数量、结果塑形、排序和分页这几个步骤。

聚合管道步骤拆解

  1. 关联Catalog集合:通过用户ID将User与所属的Catalog关联,得到用户的所有Catalog列表。
  2. 统计Catalog数量:计算关联得到的Catalog列表的长度,得到countOfCatalogs。
  3. 关联Item集合:同样通过用户ID关联用户所属的Item列表(若需通过Catalog关联Item,可调整关联条件)。
  4. 统计Item数量:计算Item列表的长度,得到countOfItems。
  5. 结果塑形:将原始用户字段封装为user对象,保留计数字段,形成Response结构。
  6. 排序:根据countOfCatalogs或countOfItems字段进行排序。
  7. 分页:通过skip和limit实现分页逻辑。

Java代码实现

假设你的MongoDB集合名称分别为user、catalog、item(若实体类使用@Document指定了集合名,请对应调整):

1. 构建聚合阶段

import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import java.util.Arrays;
import java.util.List;

// 1. 关联Catalog并过滤有效记录(可选:只统计exist=true的Catalog)
LookupOperation lookupCatalogs = LookupOperation.newLookup()
        .from("catalog")
        .localField("id")
        .foreignField("userId")
        .pipeline(Arrays.asList(Aggregation.match(Criteria.where("exist").is(true))))
        .as("catalogs");

// 2. 计算Catalog数量
AddFieldsOperation addCatalogCount = Aggregation.addFields()
        .addFieldWithValue("countOfCatalogs", AggregationExpression.from(MongoExpression.create("{ $size: \"$catalogs\" }")))
        .build();

// 3. 关联Item(若需通过Catalog关联Item,可将localField改为"catalogs.id")
LookupOperation lookupItems = LookupOperation.newLookup()
        .from("item")
        .localField("id")
        .foreignField("userId")
        .as("items");

// 4. 计算Item数量
AddFieldsOperation addItemCount = Aggregation.addFields()
        .addFieldWithValue("countOfItems", AggregationExpression.from(MongoExpression.create("{ $size: \"$items\" }")))
        .build();

// 5. 塑形为Response结构
ProjectOperation project = Aggregation.project()
        .and(Aggregation.fields()
                .and("id").as("user.id")
                .and("catalogId").as("user.catalogId")
                .and("name").as("user.name")
                .and("info").as("user.info"))
        .and("countOfCatalogs").as("countOfCatalogs")
        .and("countOfItems").as("countOfItems")
        .andExclude("_id");

// 6. 排序(示例:按countOfCatalogs降序,可根据需求动态调整)
SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "countOfCatalogs");

// 7. 分页(示例:第1页,每页10条)
int pageNum = 1;
int pageSize = 10;
SkipOperation skip = Aggregation.skip((long) (pageNum - 1) * pageSize);
LimitOperation limit = Aggregation.limit(pageSize);

2. 组装并执行聚合查询

// 组装聚合管道
Aggregation aggregation = Aggregation.newAggregation(
        lookupCatalogs,
        addCatalogCount,
        lookupItems,
        addItemCount,
        project,
        sort,
        skip,
        limit
);

// 执行查询并映射为Response列表
List<Response> responseList = mongoTemplate.aggregate(aggregation, "user", Response.class).getMappedResults();

关键注意事项

  • 集合名称匹配:确保from()方法中的集合名称与MongoDB中实际集合名一致(实体类若用@Document(collection = "xxx")注解,需对应调整)。
  • 索引优化:为catalog.userId、item.userId(或item.catalogId)创建索引,大幅提升关联查询的性能。
  • 动态排序分页:可根据前端传入的排序字段、方向和分页参数,动态构建SortOperation、SkipOperation和LimitOperation。
  • 空值处理:若用户无对应的Catalog或Item,$size会返回0,符合统计需求。

内容的提问来源于stack exchange,提问作者roditoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:42:49