# 分页与筛选接口

URL: https://caijiao.org/koa/practice/query
Source: docs/koa/practice/query.md
Description: 分页和筛选是处理大量数据时常用的两种功能，能够提高数据查询的效率和用户体验。本节将介绍如何在 Koa 中实现分页与筛选接口。

在 Web 应用中，尤其是需要展示大量数据的场景下，分页和筛选功能是不可或缺的。分页功能帮助用户分批查看数据，而筛选功能帮助用户快速定位到感兴趣的数据。

## 分页功能

分页功能可以通过请求参数来实现，通常需要传递两个参数：

- `page`：当前页码
- `limit`：每页显示的条数

通过这两个参数可以计算出数据的偏移量，从而实现分页效果。

### 分页实现示例

假设我们有一个用户数据表，下面是一个简单的分页接口实现：

```js
// user.js
const Router = require('koa-router');
const router = new Router();
const User = require('../models/user'); // 假设这是用户模型

// 获取分页用户列表
router.get('/users', async (ctx) => {
  const { page = 1, limit = 10 } = ctx.query;

  const offset = (page - 1) * limit;

  try {
    // 查询分页数据
    const users = await User.find().skip(offset).limit(limit);

    // 查询总数据量，用于计算分页信息
    const total = await User.countDocuments();

    ctx.body = {
      data: users,
      pagination: {
        page: Number(page),
        limit: Number(limit),
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  } catch (error) {
    ctx.status = 500;
    ctx.body = { message: 'Internal Server Error' };
  }
});

module.exports = router;
````

### 解释

1. `page`：客户端传入的页码，默认为 `1`。
2. `limit`：每页显示的条数，默认为 `10`。
3. `skip(offset)`：跳过前面的数据，返回当前页的数据。
4. `limit`：限制返回的数据条数。

通过这种方式，我们可以轻松地为数据添加分页功能。

## 筛选功能

筛选功能通常通过查询参数传递过滤条件来实现。例如，我们可以根据用户名、年龄、性别等字段来筛选数据。

### 筛选实现示例

假设我们想要根据用户的 `age` 和 `gender` 字段进行筛选：

```js
// user.js
const Router = require('koa-router');
const router = new Router();
const User = require('../models/user');

// 获取分页并筛选用户列表
router.get('/users', async (ctx) => {
  const { page = 1, limit = 10, age, gender } = ctx.query;

  const offset = (page - 1) * limit;

  // 构建查询条件
  const query = {};
  if (age) query.age = age;
  if (gender) query.gender = gender;

  try {
    // 查询分页数据并根据筛选条件过滤
    const users = await User.find(query).skip(offset).limit(limit);

    // 查询总数据量，用于计算分页信息
    const total = await User.countDocuments(query);

    ctx.body = {
      data: users,
      pagination: {
        page: Number(page),
        limit: Number(limit),
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  } catch (error) {
    ctx.status = 500;
    ctx.body = { message: 'Internal Server Error' };
  }
});

module.exports = router;
```

### 解释

1. `query`：构建筛选条件，只有传入的查询参数会添加到查询条件中。
2. 使用 `User.find(query)` 来查询符合条件的数据。
3. 使用 `User.countDocuments(query)` 来获取筛选后的数据总数。

## 结合分页与筛选

分页和筛选功能可以结合使用，以实现更强大的查询能力。用户可以根据筛选条件查看特定的数据，并且分页功能可以限制每次返回的数据量，优化性能。

## 总结

分页和筛选是 Web 应用中常见的数据处理需求。通过简单的查询参数，我们可以在 [Koa](/koa/) 中实现高效的分页和筛选接口。分页帮助用户按批次查看数据，而筛选帮助用户快速定位到感兴趣的数据。两者结合使用，能够提供更好的用户体验和系统性能。
