MongoDB Template如何从重复数据中仅获取单条记录?
问题
我的MongoDB数据库中存在仅_id不同、其余属性完全一致的重复数据,希望通过API仅返回每条重复数据中的一条。例如数据库中有如下结构的文档:
{ "_id": "39012fh19fh19bf21", "propertyId": 12345, "type": "STORE" }, { "_id": "69999999111", "propertyId": 12345, "type": "STORE" }
我尝试使用聚合分组操作去重,但未能成功。当前的代码实现如下:
val matchOperation = match(nestedCriteria) // 这里是一些基础过滤条件 val sortDirection = Sort.Direction.ASC val sortBy = "type" val page = PageRequest.of(...) val aggregation = newAggregation( matchOperation, sort(Sort.by(sortDirection, sortBy)), skip(page.offset), limit( page.pageSize.toLong() ) ) return mongoTemplate.aggregate(aggregation, "my_collection", MyCollectionVO::class.java) .asFlow()
我曾尝试如下分组操作及其他组合,但均未生效:
val groupOperation = group("propertyId", "type") .count().`as`("count") .first("_id").`as`("uniqueDocId") val matchOperation = match(Criteria.where("count").gt(1))
现寻求正确的实现方法。
解决方案
你之前的分组操作只获取了重复计数和单个_id,没有完整保留文档的其他字段,而且错误地筛选了count>1的分组——这会只返回存在重复的分组,而你需要的是所有数据去重后返回,不管有没有重复。
正确的实现思路和代码如下:
val matchOperation = match(nestedCriteria) // 基础过滤条件 val sortDirection = Sort.Direction.ASC val sortBy = "type" val page = PageRequest.of(...) // 按重复标识字段分组,保留每组第一个完整文档 val groupOperation = group("propertyId", "type") .first("$$ROOT").`as`("uniqueDoc") // $$ROOT代表整个原始文档 // 将分组后的文档还原为根节点格式 val replaceRootOperation = replaceRoot("uniqueDoc") // 排序、分页必须放在去重之后,避免分页结果包含重复数据 val aggregation = newAggregation( matchOperation, groupOperation, replaceRootOperation, sort(Sort.by(sortDirection, sortBy)), skip(page.offset), limit(page.pageSize.toLong()) ) return mongoTemplate.aggregate(aggregation, "my_collection", MyCollectionVO::class.java) .asFlow()
关键说明
- 使用
$$ROOT可以直接获取整个原始文档,无需手动逐个指定字段,避免遗漏属性 - 如果需要精准选择保留哪条重复数据,可以在分组前先按
_id或其他业务字段排序,确保first()拿到你想要的条目 - 分页操作必须放在去重步骤之后,否则会出现分页截断重复数据、导致结果仍有重复或丢失有效数据的问题
内容的提问来源于stack exchange,提问作者Erkan Isuf
相关产品推荐
相关产品推荐

