Elixir - 使用表关联排序

时间:2018-06-08 01:11:20

标签: elixir ecto

我正在尝试执行一个查询来获取user_posts表以及相应的关联upvotesdownvotescomments。我试过这样:

popular_posts =
  from(s in UserPost, 
    where: s.inserted_at >= ^Timex.beginning_of_month(Timex.now()),
    where: s.inserted_at <= ^Timex.end_of_month(Timex.now()),
    left_join: downvotes in assoc(s, :downvotes),
    left_join: comments in assoc(s, :comments), 
    left_join: upvotes in assoc(s, :upvotes),
    preload: [comments: comments, upvotes: upvotes, downvotes: downvotes],
    order_by: fragment("(? * 0.5) + (? * 0.1) - (? * 0.4)", ^map_size(s.upvotes), ^map_size(s.comments), ^map_size(s.downvotes)))
  |> Repo.all

但它会发出以下警告和错误:

warning: variable "s" does not exist and is being expanded to "s()", please use parentheses to remove the ambiguity or change the variable name
  lib/nethub_api_web/resolvers/content.ex:33

warning: variable "s" does not exist and is being expanded to "s()", please use parentheses to remove the ambiguity or change the variable name
  lib/nethub_api_web/resolvers/content.ex:33

warning: variable "args" is unused
  lib/nethub_api_web/resolvers/content.ex:93


== Compilation error in file lib/nethub_api_web/resolvers/content.ex ==
** (CompileError) lib/nethub_api_web/resolvers/content.ex:33: undefined function s/0
    (stdlib) lists.erl:1338: :lists.foreach/2
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

我尝试使用s更改UserPosts,但它表示表中不存在列。

2 个答案:

答案 0 :(得分:0)

这可能会有所帮助:

使用left_join

join转换为on

以下是Ecto Doc:

的示例
 from c in Comment,
  join: p in Post, on: p.id == c.post_id,
  select: {p.title, c.text}

参考: https://hexdocs.pm/ecto/Ecto.Query.html#join/5

当我有很多join时,我更喜欢使用joinon,所以我不会混淆Ecto。

同样在where之后移动join,但这并不是RDBMS中的一句老话。在Where之前加入。

Where子句中,使用where而不是第二个and。 (再次更好地在一个Ecto.Query中执行此操作,因为您没有将事情分解成碎片。

现在,如果以上都没有解决您的问题,请绕过Schema并将UserPost替换为"user_posts"并手动构建所有联接。然后 使用Ecto.Adapters.SQL.to_sql(:all, Repo, query),其中query是您的from结果,然后直接在您的数据库上运行生成的SQL并检查其中的错误,您可以在那里调整查询并将其转换回{{1} }。

现在,如果您仍然遇到问题,请直接从DB中逐个删除您的联接,以查看哪些内容已损坏。

我的建议:

答案 1 :(得分:0)

我仍然不知道为什么,但是当我改变时:

preload: [comments: comments, upvotes: upvotes, downvotes: downvotes],
order_by: fragment("(? * 0.5) + (? * 0.1) - (? * 0.4)", 
^map_size(s.upvotes), ^map_size(s.comments), ^map_size(s.downvotes)))

为:

preload: [:comments, :upvotes, :downvotes],
order_by: fragment("(? * 0.5) + (? * 0.1) - (? * 0.4)", 
^map_size(:upvotes), ^map_size(:comments), ^map_size(:downvotes)))

它按预期工作。