如何基于 Mango $lt 查询相似度?

解读

国内面试官问“**基于 Mango lt查询相似度”,并不是想听你背诵lt 查询相似度**”,并不是想听你背诵 `lt` 语法,而是考察三点:

  1. 是否理解 Mango 查询只能做精确范围过滤,本身不具备相似度计算能力
  2. 能否在 CouchDB 无内置向量/全文评分 的限制下,用业务层二次排序离线打标签的方式把“相似度”落地;
  3. 是否熟悉 CouchDB 3.x 的索引选型(JSON vs text vs 分区索引)以及 移动端同步过滤场景下的性能陷阱。

一句话:lt只是“小于”谓词,相似度必须自己“算”出来,再让lt 只是“小于”谓词,相似度必须自己“算”出来,再让 lt 帮你“取”出来。

知识点

  1. Mango 查询语法{"age":{"$lt":30}} 返回 age 字段严格小于 30 的文档,无评分、无模糊
  2. 相似度本质:把业务维度(文本、向量、行为)映射成可排序的标量分值,存成字段,如 similarity_score
  3. CouchDB 索引规则
    • similarity_score升序 JSON 索引{"index":{"fields":[{"similarity_score":"asc"}]}}
    • 查询时用 $ltTop-N 截断,例如取前 100 个最相似:
      {"selector":{"similarity_score":{"$lt":阈值}},"limit":100,"sort":[{"similarity_score":"desc"}]}
  4. 阈值来源
    • 离线批任务用 Spark+MLlib 算好 95% 分位点写回 CouchDB;
    • 或在线服务把用户向量商品向量点积后实时写入 similarity_score,再同步到移动端。
  5. 性能红线
    • 单次 Mango 查询必须命中索引,否则触发全表扫描,在百万级文档以上直接超时;
    • ltlt 与 regex 混用会导致索引失效,国内云厂商(阿里云、腾讯云)托管版 CouchDB 直接报 no_usable_index
  6. 移动同步
    • filter 函数里禁止用 $lt 做相似度过滤,因为 CouchDB 会把过滤器推给每个变更,复杂度 O(n²);
    • 正确做法是把相似度高的文档打标 flag:similar,同步端用 selector={"flag":"similar"},走预计算索引

答案

分三步落地

第一步:离线或实时计算相似度
把文本/向量相似度转成 0~1 之间的浮点分值,写入文档字段 similarity_score,并带上业务主键便于回查。

第二步:建索引
PUT /mydb/_index

{
  "index": {
    "fields": [{"similarity_score":"asc"}]
  },
  "name": "score-asc-index"
}

务必升序,因为 CouchDB 的 $lt左前缀匹配,升序索引能让 sort=[{"similarity_score":"desc"}] 仍用同一索引。

第三步:用 $lt 取 Top-N

POST /mydb/_find
{
  "selector": {
    "similarity_score": {"$lt": 0.85}
  },
  "sort": [{"similarity_score":"desc"}],
  "limit": 100
}

阈值 0.85 由离线分位点给出,保证返回的 100 条就是“最相似”的文档。
若需要用户个性化,把阈值存到用户画像表,每次查询动态拼进 selector 即可。

踩坑提醒

  • 如果 similarity_score 缺失,CouchDB 会把它当 nullnull $lt 0.85 为真,导致脏数据混入,务必加 "similarity_score":{"$exists":true}
  • 国内公有云单节点 QPS 上限约 800,高并发场景下把相似度计算迁到 ES 或 TiDB,CouchDB 只存结果快照,避免CPU 打满被客户投诉。

拓展思考

  1. 多维度相似
    若相似度由文本、价格、距离三个维度加权,可把 similarity_score 做成归一化加权和,也可以分层截断:先用 $lt 把距离小于 5 km 的文档捞出来,再在客户端用余弦相似度二次排序,兼顾精度与性能
  2. 增量更新
    采用 CouchDB 的 _changes + seq 追踪,把变更流推给 Flink 作业实时重算 similarity_score,写回时带 _rev 防止版本冲突,实现秒级更新
  3. 离线冷启动
    新用户无行为问题,把物品聚类中心预置到 cluster_id 字段,用 $lt簇内热度前 K 的文档,解决移动 App 首屏空白的痛点,国内主流内容厂商已用该方案把次日留存提升 6%
  4. 安全合规
    国内个人信息保护法要求向量特征也需脱敏,计算相似度时把用户 ID 哈希化后再落盘,防止反向推回原始手机号,审计时可直接展示索引定义而不暴露业务逻辑。