Filter API 高级过滤查询
filter API 是 Lovrabet SDK 提供的强大数据查询接口,支持复杂条件筛选、字段选择、排序和分页,是进行数据列表查询的推荐方式。
前置条件
开始之前,请确保已完成 SDK 配置。推荐使用 CLI 自动生成配置。
以下示例使用别名方式 client.models.users 以便阅读,也可以使用标准方式 client.models.dataset_xxx(功能完全一致)。
全模式支持
从 v1.1.22 版本开始,filter API 同时支持 OpenAPI 模式 和 WebAPI 模式。
🎯 主要功能
- ✅ 复杂条件查询 - 支持多条件组合、范围查询、模糊匹配等
- ✅ 字段选择 - 只返回需要的字段,减少数据传输量
- ✅ 灵活排序 - 支持多字段排序
- ✅ 分页查询 - 内置分页支持
- ✅ 类型安全 - 完整的 TypeScript 类型支持
📝 API 签名
async filter<T = any>(params?: FilterParams): Promise<ListResponse<T>>
参数说明
interface FilterParams {
where?: WhereCondition; // 查询条件
select?: string[]; // 选择返回的字段
orderBy?: SortList; // 排序规则
currentPage?: number; // 当前页码(从 1 开始,默认: 1)
pageSize?: number; // 每页数量(默认: 20)
}
返回值
interface ListResponse<T> {
tableData: T[]; // 数据列表
total: number; // 总记录数
currentPage: number; // 当前页码
pageSize: number; // 每页数量
}
🔍 Where 条件详解
条件操作符
filter API 支持以下条件操作符(所有操作符都以 $ 开头):
| 操作符 | 说明 | 示例 |
|---|---|---|
$eq | 等于 | { age: { $eq: 18 } } |
$ne | 不等于 | { status: { $ne: 'deleted' } } |
$gte / $gteq | 大于等于 | { age: { $gte: 18 } } |
$lte / $lteq | 小于等于 | { age: { $lte: 65 } } |
$in | 在集合内 | { country: { $in: ['中国', '美国'] } } |
$contain | 包含(模糊匹配) | { name: { $contain: 'hello' } } |
$startWith | 以...开头 | { email: { $startWith: 'admin' } } |
$endWith | 以...结尾 | { filename: { $endWith: '.pdf' } } |
$ 符号的作用
$ 开头的表达式是 filter API 的特殊操作符,用于表示查询条件类型。这是一种通用的查询语言约定,可以避免与普通字段名冲突。
逻辑连接符
支持 $and 和 $or 进行条件组合:
| 连接符 | 说明 | 示例 |
|---|---|---|
$and | 且(所有条件都满足) | { $and: [条件1, 条件2] } |
$or | 或(任一条件满足) | { $or: [条件1, 条件2] } |
💡 使用示例
基础查询
简单等值查询
// 查询年龄为 18 岁的用户
const result = await client.models.users.filter({
where: {
age: { $eq: 18 },
},
});
范围查询
// 查询年龄在 18-45 岁之间的用户
const result = await client.models.users.filter({
where: {
age: {
$gte: 18, // 大于等于 18
$lte: 45, // 小于等于 45
},
},
});
集合查询
// 查询来自中国、美国或日本的用户
const result = await client.models.users.filter({
where: {
country: {
$in: ["中国", "美国", "日本"],
},
},
});
模糊匹配
// 查询名字包含 "hello" 的用户
const result = await client.models.users.filter({
where: {
name: { $contain: "hello" },
},
});
// 查询邮箱以 "admin" 开头的用户
const result = await client.models.users.filter({
where: {
email: { $startWith: "admin" },
},
});
复合条件查询
AND 条件组合
// 查询 18-45 岁且来自中国的 VIP 用户
const result = await client.models.users.filter({
where: {
$and: [
{ age: { $gte: 18, $lte: 45 } },
{ country: { $eq: "中国" } },
{ vip: { $ne: null } },
],
},
});
OR 条件组合
// 查询年龄小于 18 或大于 65 的用户
const result = await client.models.users.filter({
where: {
$or: [{ age: { $lte: 18 } }, { age: { $gte: 65 } }],
},
});
混合逻辑
// 查询 VIP 用户或者活跃且来自中国的普通用户
const result = await client.models.users.filter({
where: {
$or: [
{ vip: { $eq: true } },
{
$and: [{ active: { $eq: true } }, { country: { $eq: "中国" } }],
},
],
},
});
字段选择
使用 select 参数只返回需要的字段,提高查询效率:
// 只返回 id、name、email 字段
const result = await client.models.users.filter({
where: {
country: { $eq: "中国" },
},
select: ["id", "name", "email"],
});
console.log(result.tableData);
// [
// { id: 1, name: '张三', email: 'zhangsan@example.com' },
// { id: 2, name: '李四', email: 'lisi@example.com' }
// ]
性能优化
当数据表字段很多但只需要其中几个字段时,使用 select 可以显著减少网络传输数据量和查询时间。
排序
使用 orderBy 参数指定排序规则:
// 单字段排序:按最后登录时间降序
const result = await client.models.users.filter({
where: {
country: { $eq: "中国" },
},
orderBy: [{ lastLoginAt: "desc" }],
});
// 多字段排序:先按优先级降序,再按创建时间降序
const result = await client.models.tasks.filter({
where: {
status: { $ne: "completed" },
},
orderBy: [
{ priority: "desc" }, // 第一优先级
{ createTime: "desc" }, // 第二优先级
{ name: "asc" }, // 第三优先级
],
});
分页
使用 currentPage 和 pageSize 参数进行分页:
// 获取第 2 页,每页 50 条记录
const result = await client.models.users.filter({
where: {
country: { $eq: "中国" },
},
currentPage: 2,
pageSize: 50,
});
console.log(`总数: ${result.total}`);
console.log(`当前页: ${result.currentPage}`);
console.log(`每页数量: ${result.pageSize}`);
console.log(`数据:`, result.tableData);
🎨 完整示例
示例 1:用户管理系统
import { createClient } from "@lovrabet/sdk";
const client = createClient();
// 查询活跃的中国 VIP 用户,年龄在 18-45 岁之间
// 只返回必要字段,按最后登录时间倒序排列
const result = await client.models.users.filter({
where: {
$and: [
{ age: { $gte: 18, $lte: 45 } },
{ country: { $in: ["中国", "美国", "日本"] } },
{ vip: { $ne: null } },
{ active: { $eq: true } },
{ name: { $contain: "hello" } },
],
},
select: ["id", "name", "age", "country", "lastLoginAt", "email"],
orderBy: [{ lastLoginAt: "desc" }, { name: "asc" }],
currentPage: 1,
pageSize: 20,
});
console.log(`找到 ${result.total} 个符合条件的用户`);
result.tableData.forEach((user) => {
console.log(`${user.name} (${user.age}岁) - ${user.email}`);
});
示例 2:订单查询
// 查询最近 30 天内,金额大于 100 且状态为待支付或处理中的订单
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const result = await client.models.orders.filter({
where: {
$and: [
{ createTime: { $gte: thirtyDaysAgo.toISOString() } },
{ amount: { $gte: 100 } },
{
$or: [
{ status: { $eq: "pending" } },
{ status: { $eq: "processing" } },
],
},
],
},
select: ["id", "orderNo", "amount", "status", "createTime", "customerName"],
orderBy: [{ amount: "desc" }, { createTime: "desc" }],
currentPage: 1,
pageSize: 50,
});
示例 3:搜索功能
// 实现一个搜索功能:在标题或内容中包含关键词
async function searchArticles(keyword: string, page: number = 1) {
return await client.models.articles.filter({
where: {
$or: [
{ title: { $contain: keyword } },
{ content: { $contain: keyword } },
],
},
select: ["id", "title", "summary", "author", "publishTime"],
orderBy: [{ publishTime: "desc" }],
currentPage: page,
pageSize: 10,
});
}
// 使用搜索
const results = await searchArticles("人工智能", 1);
console.log(`搜索到 ${results.total} 篇文章`);
示例 4:React 组件集成
import { useState, useEffect } from "react";
import { client } from "./api/client";
function UserList() {
const [users, setUsers] = useState([]);
const [total, setTotal] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const [loading, setLoading] = useState(false);
// 查询条件
const [filters, setFilters] = useState({
country: "中国",
minAge: 18,
maxAge: 65,
vipOnly: false,
});
useEffect(() => {
loadUsers();
}, [currentPage, filters]);
const loadUsers = async () => {
setLoading(true);
try {
const result = await client.models.users.filter({
where: {
$and: [
{ age: { $gte: filters.minAge, $lte: filters.maxAge } },
{ country: { $eq: filters.country } },
...(filters.vipOnly ? [{ vip: { $ne: null } }] : []),
],
},
select: ["id", "name", "age", "email", "country", "vip"],
orderBy: [{ vip: "desc" }, { age: "asc" }],
currentPage,
pageSize: 20,
});
setUsers(result.tableData);
setTotal(result.total);
} catch (error) {
console.error("加载用户失败:", error);
} finally {
setLoading(false);
}
};
return (
<div>
<h1>用户列表 (共 {total} 人)</h1>
{/* 过滤条件 */}
<div className="filters">
<input
type="number"
value={filters.minAge}
onChange={(e) =>
setFilters({ ...filters, minAge: Number(e.target.value) })
}
placeholder="最小年龄"
/>
<input
type="number"
value={filters.maxAge}
onChange={(e) =>
setFilters({ ...filters, maxAge: Number(e.target.value) })
}
placeholder="最大年龄"
/>
<label>
<input
type="checkbox"
checked={filters.vipOnly}
onChange={(e) =>
setFilters({ ...filters, vipOnly: e.target.checked })
}
/>
仅显示 VIP
</label>
</div>
{/* 用户列表 */}
{loading ? (
<div>加载中...</div>
) : (
<table>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>邮箱</th>
<th>VIP</th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
<td>{user.age}</td>
<td>{user.email}</td>
<td>{user.vip ? "✓" : ""}</td>
</tr>
))}
</tbody>
</table>
)}
{/* 分页 */}
<div className="pagination">
<button
disabled={currentPage === 1}
onClick={() => setCurrentPage(currentPage - 1)}
>
上一页
</button>
<span>第 {currentPage} 页</span>
<button
disabled={currentPage * 20 >= total}
onClick={() => setCurrentPage(currentPage + 1)}
>
下一页
</button>
</div>
</div>
);
}
⚠️ 注意事项
1. 操作符大小写
所有操作符都必须以小写的 $ 开头,大小写敏感:
// ✅ 正确
{
age: {
$eq: 18;
}
}
// ❌ 错误
{
age: {
$EQ: 18;
}
} // 大写不被识别
{
age: {
eq: 18;
}
} // 缺少 $
2. 条件类型
确保条件值的类型与字段类型匹配:
// ✅ 正确 - 数字字段用数字值
{
age: {
$gte: 18;
}
}
// ❌ 错误 - 数字字段用字符串值
{
age: {
$gte: "18";
}
}
// ✅ 正确 - 日期字段用 ISO 字符串
{
createTime: {
$gte: "2025-01-01T00:00:00.000Z";
}
}
3. 性能优化
- 使用
select减少返回字段 - 合理设置
pageSize,避免一次返回过多数据 - 为常用查询字段添加索引(需联系平台管理员)
📚 相关文档
有问题?查看 故障排查文档 或联系技术支持。