我想通过处理来建立具有动态顺序的查询。 基本的排序示例id +名称(见下文)可以正常工作。排序变量已插入查询中。
favorites_count_query = from(f in Favorite,
select: %{wallpaper_id: f.wallpaper_id, count: count(f.user_id)},
group_by: f.wallpaper_id)
...
sort = [asc: :id, asc: :name] # comes from request
from(w in Wallpaper,
left_join: f in subquery(favorites_count_query), on: f.wallpaper_id == w.id,
left_join: d in subquery(downloads_count_query), on: d.wallpaper_id == w.id,
select: w,
select_merge: %{favorites_count: coalesce(f.count, 0)},
select_merge: %{downloads_count: coalesce(d.count, 0)},
order_by: ^sort,
group_by: w.id)
此外,我想对计数字段(favorites_count
和downloads_count
)进行排序。将这部分放在查询中将是静态的。
...
order_by: coalesce(d.count, 0),
我现在的问题是如何像第一个使用动态变量的示例那样处理它。我没有找到解决这个问题的方法。
sort = [asc: :favorites_count, asc: :name] # comes from request
...
order_by: ^sort,
最后以Unknown column 'w0.favorites_count' in 'order clause'
order_by: ^foo(sort),
def foo(sort), do: coalesce(:count, 0)
最后以undefined function coalesce/2 (fragment/3)
使用dynamic/2
以expected a field as an atom, a list or keyword list in 'order_by', got: 'dynamic(...)'
结尾
我了解主要问题,但没有找到解决方案。有什么想法或最好的解决方案吗?感谢您的帮助!
答案 0 :(得分:1)
解决方案是多次调用order_by/3作为函数,而不是生成列表并将其直接放在from/2中。
sort = [asc: :favorites_count, asc: :name] # comes from request
from(w in Wallpaper, ...)
|> order_wallpapers(sort)
...
defp order_wallpapers(query, []), do: query
defp order_wallpapers(query, [{order, :favorites_count} = sort|others]) do
query
|> order_by([w, f, d], [{^order, f.count}])
|> order_wallpapers(others)
end
defp order_wallpapers(query, [sort|others]) do
query
|> order_by([w, f, d], ^[sort])
|> order_wallpapers(others)
end
答案 1 :(得分:-1)
我设法简化了很多,所以这是我的解决方案:
from(p in Post,
order_by: [desc_nulls_last: fragment("array_length(?, 1)", p.votes)]
)
|> Repo.all()
您可以选择desc_nulls_last
,但该片段效果很好。 array_length
是PostgreSQL特有的,所以要当心!