做视频剪辑的都知道,素材库越来越大,动辄成千上万条片段、标签、时间轴数据。前端页面不可能一次性加载所有内容,这时候后台怎么快速把数据分批“喂”上来,就成了关键。很多人用的是传统关系型数据库,但随着非结构化数据增多,比如用户行为日志、动态标签、草稿快照,NoSQL 越来越常见。可问题来了——MongoDB、Cassandra 这类 NoSQL 数据库没有标准的 LIMIT 和 OFFSET,分页咋搞?
为什么 NoSQL 分页不那么简单
在 MySQL 里写个 LIMIT 10 OFFSET 20 很轻松,可 NoSQL 多数基于分布式架构,数据分散在不同节点,OFFSET 容易造成全表扫描,性能直接拉垮。尤其是视频项目管理平台,用户翻到第5页看到的还是昨天的草稿列表,体验就差了。
用游标(Cursor)代替页码
更高效的方式是“游标分页”,也叫“键位分页”。假设你按上传时间排序查视频片段,每次请求带上上一页最后一条的时间戳或唯一 ID,下一页从这个位置继续读。这样数据库不用跳过前面的数据,直接定位,速度更快。
比如在 MongoDB 中,可以这样实现:
db.clips.find({
uploadTime: { $lt: "2024-04-05T10:00:00Z" } // 上一页最后一条的时间
})
.sort({ uploadTime: -1 })
.limit(10)
第一次请求不带条件,取最新的10条。返回时附带最后一条的 uploadTime,前端点击“下一页”时把这个值传回来,作为下一次查询起点。
复合排序键应对重复值
如果多个片段同一秒上传,时间戳一样,可能漏数据或重复。这时候加一个唯一字段组合排序,比如 _id:
db.clips.find({
$or: [
{ uploadTime: { $lt: "2024-04-05T10:00:00Z" } },
{
uploadTime: "2024-04-05T10:00:00Z",
_id: { $lt: ObjectId("...") }
}
]
})
.sort({ uploadTime: -1, _id: -1 })
.limit(10)
这种写法保证即使时间相同,也能通过 _id 继续往后翻,不会卡住。
前端交互要配合
用户习惯点“第3页”,但游标分页更适合“上一页/下一页”模式。可以在接口返回时加个 next_cursor 字段,前端隐藏具体值,只控制按钮显隐。虽然不能跳页,但对视频浏览场景够用了——谁会一口气跳到第100页找一个3秒镜头呢?
要是真想支持跳页,就得缓存每页的起始键,或者用中间层记录偏移映射,但成本高,一般小团队没必要折腾。
分页不只是技术,更是体验设计
你在剪短视频,素材库有上千个片段,滑动加载比翻页数字更自然。后端用游标分页,前端实现无限滚动,用户边拉边看,后台安静地一批批拉数据,体验顺滑很多。这背后,NoSQL 的分页逻辑其实决定了你能多快看到想要的那一帧。