Prisma ORM 是一个 Node.js 和T ypeScript 的 ORM,具有直观的数据模型、自动迁移、类型安全和自动补全功能。Prisma ORM一大亮点就是支持游标分页。游标分页使用 cursor 和 take 在给定游标之前或之后返回一组有限的结果,因此相对于传统的偏移分页具有更高的性能。
游标标记你在结果集中的位置,必须是唯一且连续的列 - 例如 ID 或时间戳。
✔ 游标分页的优点
游标分页具有扩展性。底层 SQL 不使用 OFFSET,而是查询所有 ID 大于游标值的 Post 记录。
✘ 游标分页的缺点
你必须按游标排序,而游标必须是唯一且连续的列。
你无法仅使用游标跳转到特定页面。例如,你无法准确预测哪个游标代表第 400 页(每页 20 条记录)的起始位置,而无需先请求第 1 - 399 页。
游标分页的使用场景
- 无限滚动 - 例如,按日期/时间降序排序博客文章,并一次请求 10 篇博客文章。
- 分批遍历整个结果集 - 例如,作为长时间运行的数据导出的一部分。
示例
这里是使用 Prisma 实现游标分页的示例代码。
Prisma 模式 (示例)
假设你有以下 User
模型:
model User {
id Int @id @default(autoincrement())
name String
email String @unique
// 其他字段...
createdAt DateTime @default(now())
}
游标分页查询
要实现游标分页,你需要在 Prisma 中使用 cursor
、take
和 skip
参数。
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function getUsers(cursor = null, pageSize = 10) {
let queryOptions = {
take: pageSize + 1, // 多获取一个项来检查是否有下一页
orderBy: {
id: 'asc', // 确保顺序一致
},
};
if (cursor) {
queryOptions = {
...queryOptions,
cursor: {
id: cursor,
},
skip: 1, // 跳过游标本身
};
}
const users = await prisma.user.findMany(queryOptions);
const hasNextPage = users.length > pageSize;
if (hasNextPage) {
users.pop(); // 如果多获取了一个项,移除它
}
return {
users: users,
hasNextPage: hasNextPage,
nextCursor: hasNextPage ? users[users.length - 1].id : null,
};
}
// 示例使用
getUsers(null, 10).then(result => {
console.log(result);
}).catch(error => {
console.error(error);
}).finally(() => {
prisma.$disconnect();
});
解释
初始查询设置:
- 设置查询以获取
pageSize + 1
项。多获取一个项有助于确定是否有下一页。 - 通过
id
排序以确保顺序一致。
let queryOptions = { take: pageSize + 1, orderBy: { id: 'asc', }, };
- 设置查询以获取
处理游标:
- 如果提供了游标,更新查询以从游标之后开始。
- 使用
skip: 1
跳过游标本身。
if (cursor) { queryOptions = { ...queryOptions, cursor: { id: cursor, }, skip: 1, }; }
获取数据并确定
hasNextPage
:- 从数据库中获取用户。
- 通过检查结果的长度是否大于
pageSize
来确定是否有下一页。 - 如果有下一页,移除多获取的项以返回正确数量的项。
const users = await prisma.user.findMany(queryOptions); const hasNextPage = users.length > pageSize; if (hasNextPage) { users.pop(); }
返回结果:
- 返回用户数据、一个指示是否有下一页的标志以及下一页的游标。
return { users: users, hasNextPage: hasNextPage, nextCursor: hasNextPage ? users[users.length - 1].id : null, };
示例使用
示例用法获取第一页的用户。你可以调整 cursor
参数来获取后续的页面。
getUsers(null, 10).then(result => {
console.log(result);
}).catch(error => {
console.error(error);
}).finally(() => {
prisma.$disconnect();
});
通过这种方法,你可以使用 Prisma 实现高效的游标分页。每个查询都从指定的游标开始获取固定数量的项,这对于大数据集来说非常理想,因为偏移分页在处理大数据量时可能效率不高。
评论 (0)