MongoDB C#驱动实现Keyset分页上一页数据错误如何解决?
问题根源
- 你的Keyset分页过滤条件和排序字段不匹配:当前排序规则是
CourseStartDate升序,但是过滤逻辑仅用到了Id字段,二者无关联,导致上一页过滤逻辑完全失效。且如果存在CourseStartDate重复的记录,仅用Id做游标必然会出现分页数据遗漏或重复的问题。 - 上一页查询未调整排序方向:上一页查询时你依然使用
CourseStartDate升序排序,搭配Id < lastRecordId的过滤条件,Limit 10自然会返回整个集合最靠前的10条数据,完全不符合上一页的取值逻辑。
修复方案
- 调整游标参数:前端翻页时需要同时传递当前页边界记录的
CourseStartDate和Id两个值,不要仅传Id。 - 下一页逻辑保持升序排序,过滤条件绑定排序字段:匹配大于当前页最后一条记录的游标值,直接返回查询结果。
- 上一页逻辑翻转排序方向,查询后再反转结果:匹配小于当前页第一条记录的游标值,查询得到降序的10条数据后,反转集合得到符合正常顺序的上一页数据。
修正后代码示例
var filterDef = Builders<Learner>.Filter.Where(predicate); var findOption = new FindOptions<Learner> { Limit = 10 }; if (!string.IsNullOrWhiteSpace(lastRecordId) && lastCourseStartDate.HasValue) { if (isNextPage) { // 下一页:过滤大于当前页最后一条的记录,按升序排序 filterDef &= Builders<Learner>.Filter.Or( Builders<Learner>.Filter.Gt(e => e.CourseStartDate, lastCourseStartDate.Value), Builders<Learner>.Filter.And( Builders<Learner>.Filter.Eq(e => e.CourseStartDate, lastCourseStartDate.Value), Builders<Learner>.Filter.Gt(e => e.Id, lastRecordId) ) ); findOption.Sort = Builders<Learner>.Sort.Ascending(t => t.CourseStartDate).Ascending(t => t.Id); } else { // 上一页:过滤小于当前页第一条的记录,按降序排序 filterDef &= Builders<Learner>.Filter.Or( Builders<Learner>.Filter.Lt(e => e.CourseStartDate, lastCourseStartDate.Value), Builders<Learner>.Filter.And( Builders<Learner>.Filter.Eq(e => e.CourseStartDate, lastCourseStartDate.Value), Builders<Learner>.Filter.Lt(e => e.Id, lastRecordId) ) ); findOption.Sort = Builders<Learner>.Sort.Descending(t => t.CourseStartDate).Descending(t => t.Id); } } else { // 首页默认升序 findOption.Sort = Builders<Learner>.Sort.Ascending(t => t.CourseStartDate).Ascending(t => t.Id); } var result = (await _collection.FindAsync(filterDef, findOption)).ToList(); // 上一页查询结果是降序,需要反转回升序返回 if (!isNextPage && !string.IsNullOrWhiteSpace(lastRecordId)) { result.Reverse(); } return result;
内容的提问来源于stack exchange,提问作者Haseeb Khan
相关产品推荐
相关产品推荐

