[英]Ecto: Dynamic order_by with count query on virtual field
我想通过处理来建立具有动态顺序的查询。 基本的排序示例id +名称(见下文)可以正常工作。 将sort变量插入查询中。
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(...)'
以expected a field as an atom, a list or keyword list in 'order_by', got: 'dynamic(...)'
我了解主要问题,但没有找到解决方案。 有什么想法或最好的解决方案吗? 感谢帮助!
解决方案是多次调用order_by / 3作为函数,而不是生成list并将它们直接放在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
我设法简化了很多,所以这是我的解决方案:
from(p in Post,
order_by: [desc_nulls_last: fragment("array_length(?, 1)", p.votes)]
)
|> Repo.all()
您可以选择desc_nulls_last
,但该片段效果很好。 array_length
是PostgreSQL特定的东西,所以要array_length
!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.