Fauna FQL实现connections集合关联雇主雇员文档查询
问题根因
- 第一版代码逻辑错误:关联查询逻辑全部写在
Map函数外部,connectionDoc是Map内部Lambda的局部变量,外部作用域无法访问;同时faunaClient.query仅将第一个入参识别为FQL查询语句,后续传入的关联查询逻辑会被直接忽略,因此最终只能返回connections集合本身的数据。 - 第二版代码语法错误:
Map函数的括号闭合位置错误,把Lambda回调参数排除在了Map入参之外,才会触发InvalidArity: Map function requires 2 argument(s) but 1 were given报错;此外代码还存在未定义的id变量、重复声明ref变量的问题,且雇主/雇员集合名拼写和给出的文档结构不一致(示例中集合名为employer/employee,代码中错写为复数形式employers/employees)。
正确实现代码
在Map的Lambda内部通过q.Let完成单条连接文档的关联查询即可,单次请求即可拉取所有携带关联雇主、雇员信息的连接数据:
const getConnectionsWithRelatedData = async () => { return await faunaClient.query( q.Map( // 分页拉取connections集合全量文档,若已有全量索引可替换为 q.Paginate(q.Match(q.Index("connections"))) 提升性能 q.Paginate(q.Documents(Collection("connections"))), q.Lambda( "connectionRef", q.Let( { // 读取当前遍历到的连接文档 connectionDoc: q.Get(q.Var("connectionRef")), // 提取关联的雇主、雇员ID employerId: q.Select(["data", "employerId"], q.Var("connectionDoc")), employeeId: q.Select(["data", "employeeId"], q.Var("connectionDoc")), // 构造关联文档的Ref对象 employerRef: q.Ref(Collection("employer"), q.Var("employerId")), employeeRef: q.Ref(Collection("employee"), q.Var("employeeId")), // 读取关联的雇主、雇员完整文档 employerDoc: q.Get(q.Var("employerRef")), employeeDoc: q.Get(q.Var("employeeRef")) }, // 组装最终返回的数据结构 { ref: q.Var("connectionRef"), ts: q.Select(["ts"], q.Var("connectionDoc")), data: { employer: q.Var("employerDoc"), employee: q.Var("employeeDoc"), isEmployeeApproved: q.Select(["data", "isEmployeeApproved"], q.Var("connectionDoc")), isEmployerApproved: q.Select(["data", "isEmployerApproved"], q.Var("connectionDoc")), connectionAcceptedOnDate: q.Select(["data", "connectionAcceptedOnDate"], q.Var("connectionDoc")) } } ) ) ) ) }
优化注意事项
- 若你已经为
connections集合创建了返回文档Ref的全量索引,将分页逻辑替换为q.Paginate(q.Match(q.Index("connections")))可获得更好的查询性能。 - 当集合数据量较大时,建议为
Paginate传入size参数控制单次拉取的文档数量,避免单次查询数据量过大触发超时。 - 如果业务中存在关联雇主/雇员文档被删除的场景,可以将
q.Get替换为带存在性判断的逻辑,避免单个关联文档缺失导致整个查询失败,示例:employerDoc: q.If(q.Exists(q.Var("employerRef")), q.Get(q.Var("employerRef")), null) - 请根据你实际创建的集合名称调整代码中的集合名参数,如果你的雇主、雇员集合实际为复数命名
employers/employees,对应修改Collection()内的名称即可。
内容的提问来源于stack exchange,提问作者Mathias Riis Sorensen
相关产品推荐
相关产品推荐

