如何在MongoDB中用@Query注解实现单字段去重查询并支持分页
方案1:MongoDB聚合查询(数据库层面去重,推荐)
直接在查询阶段完成去重,性能更高,分页逻辑也更准确,你可以把原Repository方法替换为使用@Aggregation注解的聚合查询:
@Aggregation(pipeline = { "{$match: {$and :[{'submitTime':{$ne:null}}, {'gameId': :#{#gameId}} ]}}", "{$sort: {'score': -1, 'timeTaken': 1, 'submitTime': 1}}", "{$group: {_id: '$userId', play: {$first: '$$ROOT'}}}", "{$replaceRoot: {newRoot: '$play'}}", "{$sort: {'score': -1, 'timeTaken': 1, 'submitTime': 1}}" }) Flux<Play> getDistinctWinners(@Param("gameId") String gameId, Pageable pageable);
逻辑说明:
- 先按你原有条件过滤符合要求的记录
- 按原排名规则排序,保证同一个用户最优的记录排在该用户所有记录的最前面
- 按userId分组,取每组第一条记录作为该用户的代表
- 把嵌套的Play数据提取为根文档,直接映射为你的实体类
- 最后重新做全局排序,配合Pageable自动完成分页的跳过、限制逻辑
方案2:Flux流层面去重(适合小数据量场景)
如果不想修改原查询逻辑,可以直接对返回的Flux流按userId做去重,只会保留同一个用户第一次出现的记录(也就是排序后的最优记录):
// 业务层处理逻辑 public Flux<Play> getDistinctWinners(String gameId, Pageable pageable) { return playRepository.getWinners(gameId, pageable) .distinct(Play::getUserId); }
注意该方案是在内存中做过滤,如果原分页查询返回的结果里同一个用户有多条记录,会导致最终返回的条数小于你设定的pageSize,数据量大时性能低于聚合方案。
内容的提问来源于stack exchange,提问作者Powsikan
相关产品推荐
相关产品推荐

