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

基于Absinthe的GraphQL项目中Elixir Ecto多表查询关联表字段过滤问题

解决Ecto查询错误:Post Schema中不存在name字段

你遇到的问题其实很直观:在处理category_name过滤条件时,你不小心用Post表的查询别名去访问Category表的name字段了,Ecto自然会抛出“字段不存在”的错误。

修正方案

要正确引用Category表的name字段,你只需要在动态拼接查询时,明确指定之前join操作中定义的Category表别名。具体修改list_posts_by_category!函数里的:category_name处理分支即可:

def list_posts_by_category!(criteria) do
  query = from p in Post,
          join: c in Category,
          on: p.category_id == c.id,
          where: p.is_published == true and is_nil(p.deleted_at)

  Enum.reduce(criteria, query, fn
    {:limit, limit}, query -> from q in query, limit: ^limit
    {:offset, offset}, query -> from q in query, offset: ^offset
    {:order, order}, query -> from q in query, order_by: [{^order, :inserted_at}, {^order, :id}]
    # 关键修改:匹配初始查询的别名,引用Category表的c.name
    {:category_name, category_name}, query -> 
      from [p, c] in query, where: c.name == ^category_name
  end)
  |> Repo.all()
end

原理说明

初始查询中我们已经通过join: c in Category给Category表指定了别名c,在后续的动态拼接环节,用[p, c]来匹配之前定义的两个表别名(Post的p和Category的c),就能正确访问Category表的name字段了。

修改后,执行你的GraphQL查询时,生成的SQL会完全符合你的预期:

SELECT p.* FROM posts p JOIN categories c ON p.category_id = c.id WHERE p.is_published = TRUE AND p.deleted_at IS NULL AND c.name = 'family' ORDER BY p.inserted_at DESC, p.id DESC

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:22:40