Search code examples
elixirecto

Elixir - Order by using table associations


I'm trying to do a query that fetches the user_posts table and the respective associations upvotes, downvotes and comments. And I tried like this:

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

But it gives the following warnings and errors:

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

I tried with changing s with UserPosts but it says that the columns don't exist in the table.


Solution

  • I still don't know why, but when I changed:

    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)))
    

    to:

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

    It worked as expected.