You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ecto.Queryable协议未实现错误:如何基于用户作用域查询关联记录?

解决Ecto.Queryable未实现错误:正确构建用户关联查询

你遇到的这个错误核心原因很明确:你把已经从数据库加载出来的实体列表传给了from宏,但Ecto的查询构建需要的是符合Ecto.Queryable协议的对象(比如Schema模块、查询结构体),而不是已经拿到的列表数据。

看你的代码,你先通过Repo.all(from p in assoc(user, :projects))拿到了projects列表,然后试图把这个列表当作查询源传入下一个from,这就违反了Ecto查询的工作逻辑——from是用来构建查询语句的,不是用来处理已加载数据的。

这里有两种更简洁且正确的写法:

方法一:直接基于User Schema构建带用户筛选的完整查询

如果已经拿到了user_id,可以直接跳过查询User实体的步骤,直接构建查询:

user_id = Map.get(Dreamhouse.Guardian.Plug.current_resource(conn), :id)

query = from(
  p in Dreamhouse.Project,
  where: p.user_id == ^user_id,
  left_join: r in assoc(p, :rows),
  left_join: i in assoc(r, :images),
  order_by: [r.index, i.index],
  preload: [rows: {r, images: i}]
)

projects = Repo.all(query)

方法二:基于已获取的User实体的关联构建查询

如果你已经拿到了user对象,也可以直接用assoc(user, :projects)作为查询起点——注意这里不要先调用Repo.all,因为assoc(user, :projects)本身返回的就是一个符合Queryable协议的Ecto.Query结构体:

user_id = Map.get(Dreamhouse.Guardian.Plug.current_resource(conn), :id)
user = Repo.get(User, user_id)

query = from(
  p in assoc(user, :projects),
  left_join: r in assoc(p, :rows),
  left_join: i in assoc(r, :images),
  order_by: [r.index, i.index],
  preload: [rows: {r, images: i}]
)

projects = Repo.all(query)

这两种写法都是在数据库层面完成完整的查询、关联和排序,不仅避免了你的类型错误,还减少了一次数据库请求,效率更高。

内容的提问来源于stack exchange,提问作者Bitwise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:42:40