如何在按ID查询的HTTP GET接口中实现返回字符串列表的分页
分页实现方案
直接按以下步骤改就行,兼容现有逻辑,改造成本很低:
1. 先定义统一的分页返回结构
不要直接返回字符串列表,要把总条数、分页参数一起返回,前端才能正常计算总页数、判断有没有上/下一页:
public class PagedResult<T> { /// <summary> /// 匹配条件的总数据条数 /// </summary> public int TotalCount { get; set; } /// <summary> /// 当前页码 /// </summary> public int PageIndex { get; set; } /// <summary> /// 每页条数 /// </summary> public int PageSize { get; set; } /// <summary> /// 当前页数据 /// </summary> public List<T> Items { get; set; } = new(); public bool HasNextPage => PageIndex * PageSize < TotalCount; public bool HasPreviousPage => PageIndex > 1; }
2. 修改控制器接口,增加分页参数
在原有参数基础上加pageIndex(页码,默认1,符合普通用户使用习惯)和pageSize(每页条数,默认20,加最大值限制防止一次拉取过多数据把服务打挂),加基础参数校验:
[Route("getLogsFileNames/{id}")] public IActionResult GetLogsFileNames(Guid id, string include = "", int pageIndex = 1, int pageSize = 20) { if (pageIndex < 1) return BadRequest("页码不能小于1"); if (pageSize is < 1 or > 100) return BadRequest("每页条数必须在1-100范围内"); return Ok(_deidentificationService.GetLogsFileNames(id, include, pageIndex, pageSize)); }
3. 修改服务层逻辑,增加分页处理
快速兼容版本(内存分页)
如果暂时没法修改底层blob查询逻辑,先在过滤完数据后做内存切片,改完就能用:
public PagedResult<string> GetLogsFileNames(Guid deviceId, string include = "", int pageIndex = 1, int pageSize = 20) { var blobs = _blobUtils.GetBlobsFromContainer(deviceId); // 原有过滤逻辑保持不变,优化写法不用冗余ForEach var filteredBlobNames = string.IsNullOrEmpty(include) ? blobs.Select(blob => blob.Name) : blobs.Where(blob => blob.Name.ToLowerInvariant().Contains(include.ToLowerInvariant())) .Select(blob => blob.Name); // 计算匹配的总条数 var total = filteredBlobNames.Count(); // 分页切片:跳过前N页的数据,取当前页需要的条数 var pageItems = filteredBlobNames .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .ToList(); return new PagedResult<string> { TotalCount = total, PageIndex = pageIndex, PageSize = pageSize, Items = pageItems }; }
4. 性能优化建议(数据量大了必须改)
上面的内存分页在单设备下blob数量少的时候没问题,如果单设备下有几千上万甚至更多blob,每次请求全量拉取所有blob元数据会非常慢,还占内存,建议做几个优化:
- 优先改
_blobUtils.GetBlobsFromContainer的底层逻辑,对接对象存储原生的分页能力(主流云厂商OSS都自带分页查询API,支持传continuation token直接拉指定页数据,不需要全量加载) - 如果数据量超过1万条,建议把页码分页改成游标分页,接口返回下一页的游标token,前端下次请求带这个token直接拿下一页,比
Skip的页码分页性能高很多,也不会因为数据新增/删除导致分页时出现重复、漏数据的问题 - 最好加固定排序规则(比如按blob上传时间倒序、按文件名字典序排序),不然对象存储默认返回的顺序可能不稳定,分页会出问题
- 大小写匹配用
ToLowerInvariant()代替ToLower(),避免多区域语言环境下匹配逻辑异常
内容的提问来源于stack exchange,提问作者CuriousCat11
相关产品推荐
相关产品推荐

