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

