PostgrSQL嵌套json_agg
我有这个问题:
def create_unique_shop_query_no_keyword(categories, shop_ids) do
products_shops_categories = from p in Product,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
distinct: s.id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [s.id, s.name],
select: %{products: fragment("json_agg( DISTINCT (?, ?, ?, ?)) AS products", p.id, p.name, p.brand, p.image), categories: fragment("json_agg( DISTINCT (?, ?)) AS category", c.id, c.name), shop: fragment("json_agg( DISTINCT (?, ?, ST_X(?), ST_Y(?))) AS shop", s.id, s.name, s.point, s.point)}
end
它将所有产品和类别都放在一个独特的商店中,但这些类别并未指向任何产品。现在我想修改它以获得所有产品在独特的商店,并在产品内,获得产品的类别。我尝试了一些变体:
def create_unique_shop_query_no_keyword(categories, shop_ids) do
products_shops_categories = from p in Product,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
distinct: s.id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [s.id, s.name],
select: %{products: fragment("json_agg( DISTINCT (?, ?, ?, ?, json_agg( DISTINCT (?, ?)) AS categories)) AS products", p.id, p.name, p.brand, p.image, c.id, c.name), shop: fragment("json_agg( DISTINCT (?, ?, ST_X(?), ST_Y(?))) AS shop", s.id, s.name, s.point, s.point)}
所有人都收到此错误:
11:57:59.819 [error] #PID<0.341.0> running Api.Router terminated
Server: 192.168.20.3:4000 (http)
Request: GET /products?categories[]=1&categories[]=2&categories[]=3&categories[]=4&categories[]=5&categories[]=6&categories[]=7&ke
yword=&latitude=-36.8597515&longitude=174.7847599&distanceFromPlaceValue=1.0&distanceFromPlaceUnit=kilometer
** (exit) an exception was raised:
** (Postgrex.Error) ERROR 42803 (grouping_error): aggregate function calls cannot be nested
(ecto) lib/ecto/adapters/sql.ex:436: Ecto.Adapters.SQL.execute_and_cache/7
(ecto) lib/ecto/repo/queryable.ex:130: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:35: Ecto.Repo.Queryable.all/4
(api) lib/api/router.ex:153: anonymous fn/1 in Api.Router.do_match/4
(api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
(api) lib/plug/debugger.ex:123: Api.Router.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
这可以使用嵌套的json_agg
吗?
将选择更改为:
select: %{products: fragment("json_agg( DISTINCT (?, ?, ?, ?, ?, ?)) AS products", p.id, p.name, p.brand, p.image, c.id, c.name), shop: fragment("json_agg( DISTINCT (?, ?, ST_X(?), ST_Y(?))) AS shop", s.id, s.name, s.point, s.point)}
有点做我想要的但是它为产品的每个类别选择一个新行,重复产品,例如这是一个独特的商店:
[%{products: [%{"f1" => 30, "f2" => "lollies", "f3" => "wonka ", "f4" => nil,
"f5" => 1, "f6" => "Meat"},
%{"f1" => 30, "f2" => "lollies", "f3" => "wonka ", "f4" => nil, "f5" => 2,
"f6" => "Dairy"},
%{"f1" => 30, "f2" => "lollies", "f3" => "wonka ", "f4" => nil, "f5" => 3,
"f6" => "Confectionary"},
%{"f1" => 31, "f2" => "peanut butter", "f3" => "kraft", "f4" => nil,
"f5" => 5, "f6" => "Baking"},
%{"f1" => 31, "f2" => "peanut butter", "f3" => "kraft", "f4" => nil,
"f5" => 6, "f6" => "Condiments"},
%{"f1" => 31, "f2" => "peanut butter", "f3" => "kraft", "f4" => nil,
"f5" => 7, "f6" => "Beverages"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 1,
"f6" => "Meat"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 2,
"f6" => "Dairy"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 3,
"f6" => "Confectionary"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 4,
"f6" => "Dessert"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 5,
"f6" => "Baking"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 6,
"f6" => "Condiments"},
%{"f1" => 36, "f2" => "a", "f3" => "a", "f4" => nil, "f5" => 7,
"f6" => "Beverages"}],
shop: [%{"f1" => 29, "f2" => "Parnell Library", "f3" => 174.780063,
"f4" => -36.863307}]},
其中f1 thorugh f4是产品字段,f5和f6是产品的类别字段。