如何在Ecto使用preload时对关联字段添加WHERE条件?
解决Ecto中结合Join与Preload过滤关联表字段的问题
你遇到的错误很典型——直接在主模型的where条件里引用了关联表的字段,而这个字段并不属于主模型MY.Model,所以Ecto会提示字段不存在。要实现你想要的SQL逻辑(关联表过滤+预加载关联数据),只需要显式Join关联表,同时保留Preload即可,具体写法如下:
正确的Ecto查询写法
query = from m in MY.Model, # 显式关联主模型与关联表,用assoc确保关联关系匹配你的schema定义 join: a in assoc(m, :accoc), # 通过关联表的别名a访问目标字段 where: a.accoc_field in [10, 11], # 保留preload加载关联数据 preload: [:accoc] Repo.all(query)
为什么这样写能解决问题?
- 明确关联表:
join: a in assoc(m, :accoc)会按照你在MY.Model中定义的关联关系,正确关联到accoc表,同时给关联表起了别名a,让你能精准访问它的字段。 - 精准过滤:
where: a.accoc_field in [10, 11]直接针对关联表的字段做过滤,和你想要的原生SQL逻辑完全对应。 - 预加载关联数据:
preload: [:accoc]会在查询主模型数据的同时,自动加载符合条件的关联accoc数据,避免额外的N+1查询问题。
你原来的错误原因
你之前的代码直接写where: q.accoc_field in [10, 11],这里的q是主模型MY.Model的别名,但accoc_field是关联表的字段,Ecto在主模型的schema中找不到这个字段,所以抛出了field does not exist的错误。
内容的提问来源于stack exchange,提问作者Kamrul Khan
相关产品推荐
相关产品推荐

