gpt4 book ai didi

sql - 如何在 Ecto 中对记录进行分组并将它们作为 map 返回?

转载 作者:行者123 更新时间:2023-11-29 12:03:06 25 4
gpt4 key购买 nike

我的数据库中有 "influencer_platforms" 表,其中包括:

id | influencer_handle | name

我想查询它们并按名称分组,例如:

%{
name1: [%{id: 1, influencer_handle: "i1"}, %{id: 3, influencer_handle: "i2"}],
name2: [%{id: 2, influencer_handle: "i3"}]
}

如何在 Ecto 中做到这一点?到目前为止,我有:

defmacrop influencer_platform_json(influencer) do
quote do
fragment(
"jsonb_agg(?)",
fragment(
"json_build_object(?, ?, ?, ?)",
"id", unquote(influencer).id,
"influencer_handle", unquote(influencer).influencer_handle
)
)
end
end

def all do
from ip in InfluencerPlatform,
group_by: :name,
select: %{
ip.name => influencer_platform_json(ip)
}
end

是一种更优雅的实现方式吗?

最佳答案

如果您希望所有这些都在数据库中完成,您可以将两个片段合二为一。如果列名是简单的常量,您也不需要将列名作为参数传递给 fragment;您可以将列名放在 fragment 中的查询中。

defmacrop influencer_platform_json(influencer) do
quote do
fragment("jsonb_agg(jsonb_build_object('id', ?, 'influencer_handle', ?))", unquote(influencer).id, unquote(influencer).influencer_handle)
end
end

您还可以获取必要的数据并使用 Enum.group_by/2 在 Elixir 中进行分组。这会更优雅,但性能可能不如上面的,具体取决于 PostgreSQL 的 JSON 处理对上述查询的优化程度。

from(ip in InfluencerPlatform, select: map(ip, [:id, :name, :influencer_handle]))
|> Repo.all
|> Enum.group_by(fn ip -> ip.name end)
# Delete `:name` from each map.
|> Enum.map(fn {k, v} ->
{k, Enum.map(v, &Map.delete(&1, :name))}
end)
|> Map.new

关于sql - 如何在 Ecto 中对记录进行分组并将它们作为 map 返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44994141/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com