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
相关产品推荐
相关产品推荐

