MongoDB C#强类型分组分页:如何高效获取总条数?
MongoDB分页分组查询与总数统计合并方案
完全可以用$facet聚合阶段将分页数据查询和分组总数统计合并为一个聚合操作,这是当前场景下最高效的方式——只需要扫描一次集合数据,避免了两次查询的重复开销。
合并后的C#实现代码
var filter = Builders<DuplicateOccurrence>.Filter.Eq(x => x.Id, occurrences.Id); var result = await _baseRepository.DbCollection().Aggregate() .Match(filter) .SortByDescending(x => x.Identifier) // 用Facet同时处理分页数据和总数统计 .Facet( // 子管道1:获取分页后的分组数据 new AggregateFacet<DuplicateOccurrence, dynamic>("data", PipelineDefinition<DuplicateOccurrence, dynamic>.Create( Builders<DuplicateOccurrence>.Group.Builders() .Group(e => e.Identifier, g => new { Identifier = g.Key, Occurred = g.Select(x => new { Id = x.Id }) }), Builders<DuplicateOccurrence>.Sort.Builders() .Skip((occurrences.CurrentPage - 1) * occurrences.PageSize), Builders<DuplicateOccurrence>.Sort.Builders() .Limit(occurrences.PageSize) )), // 子管道2:统计分组后的总条数 new AggregateFacet<DuplicateOccurrence, dynamic>("count", PipelineDefinition<DuplicateOccurrence, dynamic>.Create( Builders<DuplicateOccurrence>.Group.Builders() .Group(e => e.Identifier, g => new { }), Builders<DuplicateOccurrence>.Sort.Builders() .Count("total") )) ) .FirstOrDefaultAsync(cancellationToken); // 提取最终结果 var paginatedData = result?.Facets.First(f => f.Name == "data").Output.Cast<YourGroupedDto>().ToList(); var totalCount = result?.Facets.First(f => f.Name == "count").Output.Cast<dynamic>().FirstOrDefault()?.total ?? 0;
核心说明
$facet支持在单个聚合管道中并行执行多个子管道,一次性返回分页数据和统计结果,省去了两次查询的网络往返和重复数据扫描。- 统计总数的子管道中,先按
Identifier完成分组(仅保留分组键即可,无需额外字段),再用$count统计分组数量,得到的就是你需要的总分组条数。 - 注意将代码中的
YourGroupedDto替换为你实际使用的分组结果实体类,保证类型匹配。
内容的提问来源于stack exchange,提问作者Jimbo Jones
相关产品推荐
相关产品推荐

