必须配置foreignkey,否则jql联表查询无法识别关联关系;foreignkey需在db schema中明确定义为"目标表._id"格式,类型必须匹配,且修改后须上传生效。

uniCloud JQL 联表查询必须配 foreignKey
没配 foreignKey,collection('a,b') 或 .get() 会直接报错或返回空数组,不是语法写错,而是数据库根本不识别关联关系。这个字段必须在 DB Schema 的 JSON 文件里明确定义,不能只靠字段名相似就自动关联。
-
foreignKey必须写成"foreignKey": "目标表._id"格式,比如order表的user_id字段要关联user表,就得写"foreignKey": "user._id" - 目标表的
_id字段类型必须和外键字段一致(通常都是string),如果user._id是ObjectId类型,而order.user_id是字符串,lookup阶段会匹配失败,但不会报错,只会返回空as数组 - Schema 修改后必须点击「上传」并「生效」,仅保存文件不生效;HBuilderX 右键上传时勾选「强制覆盖」,避免本地缓存旧 Schema
多级联表只能用 aggregate(),JQL 不支持嵌套 join
JQL 的 collection('a,b,c') 是扁平化联合查询,本质是先做笛卡尔积再过滤,无法表达“a→b→c”的链式引用。比如订单 → 用户 → 用户头像表,必须拆成聚合管道,不能靠单条 JQL 语句搞定。
- 第一级
lookup关联用户:用order.user_id→user._id - 第二级
lookup必须基于上一级输出字段,比如用户数据存在as: 'user_info',那下一级就要从$user_info._id出发,关联头像表 - 中间必须加
unwind:如果第一级lookup返回的是数组(哪怕只匹配到一条),第二级lookup会因字段路径错误失败,unwind('$user_info')把数组转为对象才能继续引用 - 字段别名不能重复:两个
lookup的as值必须不同,比如as: 'user_info'和as: 'avatar_info',否则后一个会覆盖前一个
uniCloud-db 组件不支持多级联表,只能用云函数封装
<unicloud-db></unicloud-db> 组件底层调用的是 JQL,它只支持单层 collection('a,b') 或带简单 where 的联合查询。一旦涉及三级以上关联、unwind、project 字段裁剪或复杂 match,组件就会静默失败或返回结构错乱的数据。
- 前端直接调用
collection().aggregate()会触发权限拦截,因为客户端 SDK 默认禁止聚合操作——这是安全机制,不是 bug - 必须把多级聚合逻辑写在云函数或云对象里,前端只调用
callFunction或importObject - 云函数内要用
uniCloud.database()实例,不能用uniCloud.db(后者是客户端实例,不支持aggregate) - 如果云函数返回数据量大,记得在
end()前加limit(20)和skip(),否则可能超内存或超时
性能陷阱:lookup 放在 match 后面会全表扫描
聚合管道顺序直接影响性能。把 match 过滤条件写在 lookup 之后,数据库会先关联所有记录,再筛选,数据量稍大就卡死。正确顺序是:先 match 主表,再 lookup,最后 match 关联字段。
- 错误写法:
.lookup(...).match({ 'user_info.status': 1 })—— 先关联全部用户,再筛状态 - 正确写法:
.match({ status: 1 }).lookup(...).match({ 'user_info.nickname': /张/ })—— 先筛订单,再关联,最后筛用户昵称 - 对被关联表加索引:在
user表的_id字段建索引(默认已有),但在avatar表的user_id字段也得手动建索引,否则二级lookup极慢 - 避免在
lookup的as字段上做$regex模糊查询,MongoDB 不会走索引,应改用text索引 +$text查询
foreignKey 的拼写格式和聚合管道中 unwind 的必要性——前者导致查不到数据却无报错,后者导致后续 lookup 字段路径失效,问题现象都像“数据为空”,但根因完全不同。











