如何只上传 Top-5 结果?
解读
国内面试场景下,面试官抛出“只上传 Top-5 结果”通常不是让你手写 SQL 的 LIMIT 5,而是考察你对 CouchDB 视图(View)机制、Map 端过滤、Reduce 排序、HTTP 分页参数以及 客户端二次裁剪 的综合理解。
核心矛盾:CouchDB 视图默认返回全量有序数据,而业务只让“上传”5 条。
“上传”一词在国内语境里常被口语化地指“把结果给到上游系统/前端”,所以你要回答的是“如何让 CouchDB 只吐出 5 条最符合业务排序条件的数据,再交给下游”。
知识点
- Map 函数:在视图中 emit(key, value) 决定排序键。
- Reduce 函数:_count、_sum、_stats 等内置或自定义,用于聚合;不可直接做 Top-N。
- 视图查询参数:
- descending=true/false
- startkey/endkey
- limit=n(硬性截断)
- skip=m(性能黑洞,线上慎用)
- 书签(bookmark)与分页:CouchDB 2.x+ 支持稳定分页,但 limit 与 skip 组合仍可能全表扫。
- 客户端二次排序:若业务排序字段与视图 key 不一致,需拉取候选集再裁剪。
- 国内网络与合规:移动端弱网、跨省 CDN 回源时,limit 过大易造成 504,Top-5 是典型安全阈值。
答案
步骤如下,每一步都要在面试时口述清楚:
-
设计视图
在 design doc 里新建视图top_sales,Map 函数按销售额倒序 emit:function (doc) { if (doc.type === 'order' && doc.amount) { emit(-doc.amount, {_id: doc._id, amount: doc.amount}); } }负号实现倒序,避免 Reduce。
-
查询时直接 limit=5
GET /db/_design/orders/_view/top_sales?limit=5&reduce=falseCouchDB 会在 B+Tree 上提前停扫,只读 5 条,时间复杂度 O(logN+5),不会全表扫。
-
结果交给上游
把返回的 5 行 JSON 直接 POST 给业务网关;若上游要求数组打包,再包一层即可。
关键点:limit 由 CouchDB 服务端完成,网络传输也只有 5 条,符合“只上传 Top-5”的硬性要求。 -
防并发更新导致跳变
国内电商大促场景下,数据实时变化,可在上传前带update_seq作为快照版本号,供下游判重。
拓展思考
-
如果排序维度是复合指标(销售额×权重),而视图只能单 key,怎么办?
答:在 Map 里预计算综合得分并 emit,把业务公式下沉到视图;若公式常变,则 emit 原始值,客户端拉 20 条再二次排序裁 5 条,牺牲带宽换灵活。 -
数据量大到分片集群(国内公有云 CouchDB 3.x 集群版),limit 5 会不会跨 shard 放大?
答:CouchDB 使用 merge-sort on the fly,协调节点只需每个 shard 取 5 条,再归并 5 条,网络放大系数=shard 数×5,仍是常数级;但 shard 过多时协调节点 CPU 会成为瓶颈,国内经验值:单库 shard≤64。 -
需要离线优先的 PouchDB 场景,移动端也只想存 Top-5,怎么同步?
答:在sync事件里加filter函数,只让 _id 在 Top-5 列表里的文档通过;Top-5 列表由云端定时算好写进一个配置文档,移动端先拉配置再按需同步,节省 90% 流量,符合国内运营商套餐限制。