mcpField
P
pagination

pagination

github.com/claude-dev-suite开发4638 次安装2 天前更新
代码仓库

关于 pagination

为开发者提供 API 分页实现参考,比较游标、偏移和键集分页,并涵盖过滤、排序及生产实践。

主要功能

  1. 01游标、偏移与键集分页模式
  2. 02过滤和排序示例
  3. 03页大小与输入验证
  4. 04生产检查清单

适用场景

  1. 01为大型数据集选择分页方式
  2. 02为管理端点添加分页
  3. 03检查分页边界情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill pagination

安装后在 Claude Code 中输入/pagination确认已加载。

详细介绍

分页

基于游标(推荐用于大型数据集)

app.get('/api/products', async (req, res) => {
  const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);
  const cursor = req.query.cursor as string | undefined;

  const where: any = {};
  if (cursor) {
    where.id = { gt: cursor };
  }

  const items = await db.product.findMany({
    where,
    take: limit + 1, // Fetch one extra to check hasMore
    orderBy: { id: 'asc' },
  });

  const hasMore = items.length > limit;
  if (hasMore) items.pop();

  res.json({
    data: items,
    pagination: {
      hasMore,
      nextCursor: hasMore ? items[items.length - 1].id : null,
    },
  });
});

基于偏移量(简单,适合小型数据集)

app.get('/api/products', async (req, res) => {
  const page = Math.max(parseInt(req.query.page as string) || 1, 1);
  const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);
  const offset = (page - 1) * limit;

  const [items, total] = await Promise.all([
    db.product.findMany({ skip: offset, take: limit, orderBy: { createdAt: 'desc' } }),
    db.product.count(),
  ]);

  res.json({
    data: items,
    pagination: {
      page, limit, total,
      totalPages: Math.ceil(total / limit),
      hasMore: offset + items.length < total,
    },
  });
});

筛选和排序

app.get('/api/products', async (req, res) => {
  const { sort = 'createdAt', order = 'desc', category, minPrice, maxPrice, search } = req.query;

  const where: any = {};
  if (category) where.category = category;
  if (minPrice || maxPrice) {
    where.price = {};
    if (minPrice) where.price.gte = parseFloat(minPrice as string);
    if (maxPrice) where.price.lte = parseFloat(maxPrice as string);
  }
  if (search) where.name = { contains: search, mode: 'insensitive' };

  const items = await db.product.findMany({
    where,
    orderBy: { [sort as string]: order },
    take: limit,
    skip: offset,
  });

  res.json({ data: items, pagination: { /* ... */ } });
});

Spring Boot(Pageable)

@GetMapping("/products")
public Page<ProductDto> list(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "20") int size,
    @RequestParam(defaultValue = "createdAt,desc") String[] sort) {

    Pageable pageable = PageRequest.of(page, Math.min(size, 100),
        Sort.by(Sort.Direction.fromString(sort[1]), sort[0]));
    return productRepo.findAll(pageable).map(mapper::toDto);
}

对比

策略优点缺点最适用于
偏移量简单,可跳转到指定页大型表中速度慢,跳过的数据会漂移管理面板、小型数据集
游标速度快,插入数据时结果稳定无法跳转到第 N 页信息流、无限滚动、大型数据集
键集速度快,不会出现跳过的数据漂移多列排序较复杂时间序列、有序数据

反模式

反模式修正方法
未限制最大页面大小限制 limit(例如,最大为 100)
在超大表上使用 COUNT(*)使用游标分页,跳过总数统计
在数百万行数据上使用偏移量使用游标或键集分页
返回所有字段仅选择所需字段,支持 fields 参数
未设置默认排序始终定义默认排序,以确保结果稳定

生产环境检查清单

  • 强制限制最大页面大小(例如,100)
  • 定义默认排序顺序
  • 对大型或持续增长的数据集使用游标分页
  • 验证 page/limit/sort 参数
  • 使用一致的响应封装(data、pagination)

评论

支持 Markdown