我在phoenix
应用程序中使用了postgresql数据库。我有一个buses
表,每个表都与一个或多个stops
和routes
相关联。我正在尝试列出所有站点的可搜索列表,但是我不想重写我的搜索和过滤功能(请参见list_filtered_buses
)。
因此,在sort_bus_list
中,我试图返回所有停靠站的排序列表。
当前实施方式的问题是,由于在返回每个总线的所有停靠点后,在模板中呈现列表时会返回重复项。我尝试了两种不同的方法,一种返回重复项,还有一个可以防止由于错误而进行排序。
这是buses.ex
中sort_bus_list中的相关代码:
# V1 - sortable, but returns duplicates
list
|> order_by([b, s, r], {^attrs.sort_dir, field(s, ^attrs.sort_attr)})
|> group_by([b, s, r], [s.id, b.id])
# V2 - doesn't return duplicates, but isn't returns error:
# ERROR 42803 (grouping_error): column "b1.stop_id" must appear in the GROUP BY clause or be used in an aggregate function
list
|> order_by([b, s, r], {^attrs.sort_dir, field(s, ^attrs.sort_attr)})
|> group_by([b, s, r], b.id)
这是我模板的伪代码:
for bus in Buses
for stop in bus
display stop
end
end
更多buses.ex
代码用于上下文:
def list_filtered_buses(params) do
search_term = params["filter"]["query"]
from(t in Bus, join: a in assoc(t, :stops), join: c in assoc(t, :routes))
|> search(search_term)
|> list_buses_by_active(params)
|> list_buses_by_type(params)
|> sort_buses_list(params)
|> preload([:stops, :routes])
end
def sort_bus_list(list, params) do
attrs = process_sorting_metrics(params)
case params["filter"]["sort_attr"] do
a when a == "stop_name" or a == "stop_id" ->
#V2 - sortable, but returns duplcate
list
|> order_by([b, s, r], {^attrs.sort_dir, field(s, ^attrs.sort_attr)})
|> group_by([b, s, r], [s.id, b.id])
"route_name" ->
list
|> order_by([b, s, r], {^attrs.sort_dir, field(r, ^attrs.sort_attr)})
|> group_by([b, s, r], [b.id, r.id])
_ ->
list
|> order_by([b, s, r], {^attrs.sort_dir, field(b, ^attrs.sort_attr)})
|> group_by([b, s, r], b.id)
end
end
答案 0 :(得分:1)
看起来,您正在尝试仅渲染Stop
。在list_filtered_buses
函数中,您正在Bus
表上运行查询。然后,您进一步尝试对数据进行排序和分组。 #V1函数正在Bus.id
和Stop.id
上进行分组,因此如果不同的Stop
具有相同的Bus
,则会得到重复的Stop
。但是,#V2函数返回错误,因为您正在select
上进行Bus
查询,而仅在group
。id上进行Bus
,并尝试从Stop
。
如@AlekseiMatiushkin所建议的,为了仅渲染不同的Stop
,需要执行from(s in Stop)
。