-
-
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
Spread operator for many-to-many relationships, aliases, and aggregations #3041
Comments
Just thought of a complex example here. Imagine that you want to get all the related posts. Related posts are posts that share the same tags as the current posts sorted by relevance (number of duplicate posts found). Imagine if you could just do this: GET /posts?select=...tags(posts(*,count))&id=eq.0x123&posts.id=not.eq.0x123&order=count Instead of a custom function like this: DROP FUNCTION IF EXISTS related_posts;
CREATE OR REPLACE FUNCTION related_posts(id uuid)
RETURNS SETOF posts
LANGUAGE sql
AS $$
SELECT p.*
FROM posts p
JOIN tags t1 ON p.id = t1.pid
JOIN tags t2 ON t1.name = t2.name
AND t2.pid = related_posts.id
WHERE p.id != related_posts.id
AND p.status = 'published'
GROUP BY
p.id,
p.parent,
p.status,
p.title,
p.author,
p.content,
p.image,
p.slug,
p.minutes,
p.created_at,
p.updated_at,
p.published_at
ORDER BY count(*) DESC;
$$; This would technically require you to be able to put This would also solve a lot of Group By problems: J |
@jdgamble555 Sounds like a good idea. We've been wanting this for aggregate functions #2925. I'm thinking the rule should be to allow to-many spreads if there's only aggregates (no other columns) on the embedded relation. This to ensure there's only one row present.
To be consistent with the current syntax: GET /posts?select=title,...tags(name) The restriction for to-many spreading for this case would be to have a single column on the embedded relation.
Looks related to #2730. If we solve spread on aggregates I believe this will come for free.
That one doesn't seem that useful. The user would have to match both arrays to get the complete data and we'd need to ensure the order somehow. Seems hard to implement too. Not sure yet of the shape of the queries. |
I would love this to be a thing! |
I'm giving this a shot in #3640. My approach is to wrap all the selected columns in curl 'localhost:3000/clients?select=name,...projects(name,id)' Would roughly translate to: SELECT "test"."clients"."name",
"clients_projects_1"."name",
"clients_projects_1"."id"
FROM "test"."clients"
LEFT JOIN LATERAL (
SELECT json_agg("projects_1"."name") AS "name",
json_agg("projects_1"."id") AS "id"
FROM "test"."projects" AS "projects_1"
WHERE "projects_1"."client_id" = "test"."clients"."id"
) AS "clients_projects_1" ON TRUE Then, the response would be: [
{"name":"Microsoft","name":["Windows 7", "Windows 10"],"id":[1, 2]},
{"name":"Apple","name":["IOS", "OSX"],"id":[3, 4]}
] I'll be updating any caveats I encounter in the PR. |
Currently the spread operator works on
one-to-one
andmany-to-one
relationships. We need to get it to work in all situations likemany-to-many
relationships:Schema:
Spread on Item
Response:
Spread on Count
Response:
Sort by Foreign Column (with alias and spread)
Would help with the sorting by foreign column:
Multiple Levels
Of course if you model your tags with a junction table, you need something like this that works for multiple levels:
Response:
Spread on Table (with duplicate column name)
I'm not sure how useful this one would be, as this may could be translated differently.
Response:
I think the spread operator has so much potential to simplify things. It could also simplify the queries under the hood.
J
The text was updated successfully, but these errors were encountered: