api-filtering-sorting

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Filtering & Sorting

API过滤与排序

Build flexible filtering and sorting systems that handle complex queries efficiently.
构建可高效处理复杂查询的灵活过滤与排序系统。

Query Parameter Syntax

查询参数语法

GET /products?category=electronics&price[gte]=100&price[lte]=500&sort=-price,name
GET /products?category=electronics&price[gte]=100&price[lte]=500&sort=-price,name

Implementation (Node.js)

实现示例(Node.js)

javascript
const allowedFilters = ['category', 'status', 'price', 'createdAt'];
const allowedSorts = ['name', 'price', 'createdAt'];

app.get('/products', async (req, res) => {
  const filter = {};
  const sort = {};

  // Parse filters
  for (const [key, value] of Object.entries(req.query)) {
    if (key === 'sort') continue;

    const match = key.match(/^(\w+)\[(\w+)\]$/);
    if (match) {
      const [, field, operator] = match;
      if (!allowedFilters.includes(field)) continue;
      filter[field] = { [`$${operator}`]: parseValue(value) };
    } else if (allowedFilters.includes(key)) {
      filter[key] = value;
    }
  }

  // Parse sort
  if (req.query.sort) {
    for (const field of req.query.sort.split(',')) {
      const direction = field.startsWith('-') ? -1 : 1;
      const name = field.replace(/^-/, '');
      if (allowedSorts.includes(name)) sort[name] = direction;
    }
  }

  const products = await Product.find(filter).sort(sort);
  res.json({ data: products });
});

function parseValue(value) {
  if (value === 'true') return true;
  if (value === 'false') return false;
  if (!isNaN(value)) return Number(value);
  return value;
}
javascript
const allowedFilters = ['category', 'status', 'price', 'createdAt'];
const allowedSorts = ['name', 'price', 'createdAt'];

app.get('/products', async (req, res) => {
  const filter = {};
  const sort = {};

  // Parse filters
  for (const [key, value] of Object.entries(req.query)) {
    if (key === 'sort') continue;

    const match = key.match(/^(\w+)\[(\w+)\]$/);
    if (match) {
      const [, field, operator] = match;
      if (!allowedFilters.includes(field)) continue;
      filter[field] = { [`$${operator}`]: parseValue(value) };
    } else if (allowedFilters.includes(key)) {
      filter[key] = value;
    }
  }

  // Parse sort
  if (req.query.sort) {
    for (const field of req.query.sort.split(',')) {
      const direction = field.startsWith('-') ? -1 : 1;
      const name = field.replace(/^-/, '');
      if (allowedSorts.includes(name)) sort[name] = direction;
    }
  }

  const products = await Product.find(filter).sort(sort);
  res.json({ data: products });
});

function parseValue(value) {
  if (value === 'true') return true;
  if (value === 'false') return false;
  if (!isNaN(value)) return Number(value);
  return value;
}

Filter Operators

过滤操作符

OperatorMeaningExample
eqEquals
?status=active
neNot equals
?status[ne]=deleted
gt/gteGreater than
?price[gte]=100
lt/lteLess than
?price[lte]=500
inIn array
?status[in]=active,pending
likeContains
?name[like]=phone
操作符含义示例
eq等于
?status=active
ne不等于
?status[ne]=deleted
gt/gte大于/大于等于
?price[gte]=100
lt/lte小于/小于等于
?price[lte]=500
in在数组范围内
?status[in]=active,pending
like包含
?name[like]=phone

Security

安全注意事项

  • Whitelist allowed filter fields
  • Validate input types per field
  • Index frequently-filtered columns
  • Limit query complexity
  • Prevent SQL/NoSQL injection
  • 白名单允许的过滤字段
  • 按字段验证输入类型
  • 为频繁过滤的列创建索引
  • 限制查询复杂度
  • 防止SQL/NoSQL注入

Best Practices

最佳实践

  • Support common operators
  • Cache filter option lists
  • Monitor query performance
  • Provide sensible defaults
  • 支持常用操作符
  • 缓存过滤选项列表
  • 监控查询性能
  • 提供合理的默认值