-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple "hops" for embed(Unnest/flatten embeds) #1233
Comments
@blainehansen #1075(pending enhancement) would clear the Doing embeds like |
Is there any intention of a feature like this? Or should I just close? Thank you 😄 |
Not with "multiple hops" but I think we can offer "flattening" by using PostgreSQL json arrow operators, in your example this would look like: "/dimension?
select=*,
relationships:dimension_relationship.ancestor_id(
attribute:dimension.descendent_id(*)
)->attribute
&dimension_type_name=eq.a
&relationships.attribute.dimension_type_name=eq.b" |
Using some our test suite fixtures( GET /tasks?select=name,projects(*,client_name:clients(*)->name) [{"name":"Design w7","projects":{"id":1,"name":"Windows 7","client_name":"Microsoft"}},
{"name":"Code w7","projects":{"id":1,"name":"Windows 7","client_name":"Microsoft"}},
{"name":"Design w10","projects":{"id":2,"name":"Windows 10","client_name":"Microsoft"}}
{"name":"Code w10","projects":{"id":2,"name":"Windows 10","client_name":"Microsoft"}},
{"name":"Design IOS","projects":{"id":3,"name":"IOS","client_name":"Apple"}},
{"name":"Code IOS","projects":{"id":3,"name":"IOS","client_name":"Apple"}},
{"name":"Design OSX","projects":{"id":4,"name":"OSX","client_name":"Apple"}},
{"name":"Code OSX","projects":{"id":4,"name":"OSX","client_name":"Apple"}}] This would generate the following query: with pg_source as (
select
"test"."tasks"."name",
row_to_json("projects_projects".*) as "projects"
from "test"."tasks"
left join lateral(
select
"test"."projects"."id",
"test"."projects"."name",
row_to_json("clients_clients".*)->'name' as "client_name"
from "test"."projects"
left join lateral(
select
"test"."clients"."id",
"test"."clients"."name"
from "test"."clients"
where "test"."clients"."id" = "test"."projects"."client_id" ) as "clients_clients" on true
where "test"."projects"."id" = "test"."tasks"."project_id" ) as "projects_projects" on true )
select coalesce(json_agg(_postgrest_t), '[]')::character varying as body
from ( select * from pg_source) _postgrest_t; I think this would be useful and we'd only have to allow the @blainehansen Thanks for the report, this feature will be in the plans. |
Another option for syntax is using the JS spread operator. So instead of:
Use: GET /tasks?select=name,projects(*,...clients(client_name:name)) With this the full object can get flattened as well: GET /tasks?select=name,projects(*,...clients(*)) [{"name":"Design w7","projects":{"id":1,"name":"Windows 7","id":1,"name":"Microsoft"}},
{"name":"Code w7","projects":{"id":1,"name":"Windows 7","id":1,"name":"Microsoft"}},
{"name":"Design w10","projects":{"id":2,"name":"Windows 10","id":1,"name":"Microsoft"}},
{"name":"Code w10","projects":{"id":2,"name":"Windows 10","id":1,"name":"Microsoft"}},
{"name":"Design IOS","projects":{"id":3,"name":"IOS","id":2,"name":"Apple"}},
{"name":"Code IOS","projects":{"id":3,"name":"IOS","id":2,"name":"Apple"}},
{"name":"Design OSX","projects":{"id":4,"name":"OSX","id":2,"name":"Apple"}},
{"name":"Code OSX","projects":{"id":4,"name":"OSX","id":2,"name":"Apple"}}] This only seems to make sense for many-to-one and one-to-one relationships. |
Yes, I like that, I suggested that a while back, too. |
Now that we have some logic to enforce the to-one relationship(on #2511), this should be just a matter of defining the query. Which I think should be simple like this: -- Go from
WITH pgrst_source AS (
SELECT
"test"."projects".*,
row_to_json("projects_clients_1".*) AS "clients"
FROM "test"."projects"
LEFT JOIN LATERAL (
SELECT
"clients_1".id as client_id,
"clients_1".name as client_name
FROM "test"."clients" AS "clients_1"
WHERE "clients_1"."id" = "test"."projects"."client_id"
) AS "projects_clients_1" ON TRUE
)
SELECT
coalesce(json_agg(_postgrest_t), '[]')::character varying AS body
FROM ( SELECT * FROM pgrst_source ) _postgrest_t;
body
---------------------------------------------------------------------------------------------------
[{"id":1,"name":"Windows 7","client_id":1,"clients":{"client_id":1,"client_name":"Microsoft"}}, +
{"id":2,"name":"Windows 10","client_id":1,"clients":{"client_id":1,"client_name":"Microsoft"}}, +
{"id":3,"name":"IOS","client_id":2,"clients":{"client_id":2,"client_name":"Apple"}}, +
{"id":4,"name":"OSX","client_id":2,"clients":{"client_id":2,"client_name":"Apple"}}, +
{"id":5,"name":"Orphan","client_id":null,"clients":null}]
-- To
WITH pgrst_source AS (
SELECT
"test"."projects".*,
"projects_clients_1".*
FROM "test"."projects"
LEFT JOIN LATERAL (
SELECT
"clients_1".name as client_id,
"clients_1".name as client_name
FROM "test"."clients" AS "clients_1"
WHERE "clients_1"."id" = "test"."projects"."client_id"
) AS "projects_clients_1" ON TRUE
)
SELECT
coalesce(json_agg(_postgrest_t), '[]')::character varying AS body
FROM ( SELECT * FROM pgrst_source ) _postgrest_t;
body
-------------------------------------------------------------------------------------------------
[{"id":1,"name":"Windows 7","client_id":1,"client_id":"Microsoft","client_name":"Microsoft"}, +
{"id":2,"name":"Windows 10","client_id":1,"client_id":"Microsoft","client_name":"Microsoft"}, +
{"id":3,"name":"IOS","client_id":2,"client_id":"Apple","client_name":"Apple"}, +
{"id":4,"name":"OSX","client_id":2,"client_id":"Apple","client_name":"Apple"}, +
{"id":5,"name":"Orphan","client_id":null,"client_id":null,"client_name":null}] It boils down to removing the |
Environment
docker
postgres:10-alpine
docker
postgrest/postgrest
(pulled fresh this morning)Ubuntu 18
Description of issue (less an issue than a question)
Is it possible to do multiple "hops" to embed something?
For example, I have a schema similar to this (the real thing has more columns and checks)
The basic idea behind this structure is that it can store any arbitrary hierarchy of data. The relationships can only go in one direction, but it doesn't have to be tree-like (a dimension can can multiple parents).
I want to get a particular dimension (let's say with
dimension_type_name
"a"), and all the descendent dimensions withdimension_type_name
"b", in a json structure similar to this:This gets me close:
But there's an extra level of nesting that I don't want, and a bunch of null attributes:
Is something akin to this supported?
Here's a sql schema you can use to quickly get running with this structure:
The text was updated successfully, but these errors were encountered: