MongoDB多条件查询:按LID筛选、KID去重并保留最新pointDate记录
MongoDB 查询方案及JPA适配说明
一、MongoDB 聚合查询语句
要实现筛选LID=45且KID为44或28,同时对重复KID保留pointDate最新记录的需求,可通过MongoDB聚合管道完成,具体语句如下:
db.collection.aggregate([ // 筛选符合条件的记录 { $match: { LID: "45", KID: { $in: [44, 28] } } }, // 按KID升序、pointDate降序排序,确保同一KID下最新记录排在首位 { $sort: { KID: 1, pointDate: -1 } }, // 按KID分组,取每组第一条(即最新)记录 { $group: { _id: "$KID", latestRecord: { $first: "$$ROOT" } } }, // 将分组后的最新记录还原为原文档结构 { $replaceRoot: { newRoot: "$latestRecord" } } ])
语句说明:
$match:精准过滤目标LID和指定KID范围的记录;$sort:对筛选结果排序,保证同一KID下最新的记录排在最前面;$group:以KID为分组键,通过$first获取每组的首条记录(即最新记录);$replaceRoot:把分组后嵌套的latestRecord字段提升为根文档,恢复原始数据结构。
二、Spring Data JPA(MongoDB)适配方案
Spring Data MongoDB的Repository接口没有直接提供这类“分组取最新记录”的现成方法,需通过自定义聚合查询实现,主要有两种方式:
方式1:使用@Aggregation注解
在自定义Repository接口中添加带注解的方法,直接嵌入聚合逻辑:
import org.springframework.data.mongodb.repository.Aggregation; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; public interface YourEntityRepository extends MongoRepository<YourEntity, Long> { @Aggregation(pipeline = { "{ '$match': { 'LID': ?0, 'KID': { '$in': ?1 } } }", "{ '$sort': { 'KID': 1, 'pointDate': -1 } }", "{ '$group': { '_id': '$KID', 'latestRecord': { '$first': '$$ROOT' } } }", "{ '$replaceRoot': { 'newRoot': '$latestRecord' } }" }) List<YourEntity> findLatestByLidAndKidIn(String lid, List<Integer> kidList); }
方式2:使用MongoTemplate手动构建聚合
如果需要更灵活的逻辑控制,可直接用MongoTemplate构建聚合操作:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Criteria; import java.util.Arrays; import java.util.List; public class YourService { private final MongoTemplate mongoTemplate; public YourService(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public List<YourEntity> getLatestRecords() { Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(Criteria.where("LID").is("45").and("KID").in(Arrays.asList(44, 28))), Aggregation.sort(Sort.by(Sort.Order.asc("KID"), Sort.Order.desc("pointDate"))), Aggregation.group("KID").first("$$ROOT").as("latestRecord"), Aggregation.replaceRoot("latestRecord") ); AggregationResults<YourEntity> results = mongoTemplate.aggregate(aggregation, "collectionName", YourEntity.class); return results.getMappedResults(); } }
内容的提问来源于stack exchange,提问作者Masoom Raza
相关产品推荐
相关产品推荐

