diff --git a/2022-12-00-redwood-retro-lists/ten-ways-to-become-better-redwood-developer.md b/2022-12-00-redwood-retro-lists/ten-ways-to-become-better-redwood-developer.md index 811c5545..90ca120f 100644 --- a/2022-12-00-redwood-retro-lists/ten-ways-to-become-better-redwood-developer.md +++ b/2022-12-00-redwood-retro-lists/ten-ways-to-become-better-redwood-developer.md @@ -10,6 +10,17 @@ 1. Postgres CTEs & Window Functions + Prisma is a great ORM, but sometimes you need to go native and write raw SQL to perform complex calculations or queries. + + ### Common Table Expressions (CTEs) + + - "mini temp tables" with selected data that you can query in subsequent selects + - break down very large queries into management steps + - the `WITH` + - WITH provides a way to write auxiliary statements for use in a larger query. These statements, which are often referred to as Common Table Expressions or CTEs, can be thought of as defining temporary tables that exist just for one query. + - https://www.postgresql.org/docs/15/queries-with.html + - Extra credit `RECURSIVE` and `UNION` queries + ### Window Functions - Window functions provide the ability to perform calculations across sets of rows that are related to the current query row @@ -99,8 +110,82 @@ 1. Postgres Functions & Triggers + - Triggers can calculate on insert, update, delete + - See updating [vote counts example](https://github.com/supabase-community/supabase-graphql-example/blob/main/data/supabase/06-update-post-vote-counts.sql) for the [supanews](https://supabase-graphql-example.vercel.app) demo + + ```sql + CREATE OR REPLACE FUNCTION public.update_vote_counts() + RETURNS trigger as $$ + BEGIN + + WITH r AS ( + SELECT + coalesce("Vote"."postId", "Post".id) AS "postId", + count(1) "voteTotal", + count(1) FILTER (WHERE direction = 'UP') "upVoteTotal", + count(1) FILTER (WHERE direction = 'DOWN') "downVoteTotal", + coalesce(sum( + CASE WHEN direction = 'UP' THEN + 1 + WHEN direction = 'DOWN' THEN + -1 + ELSE + 0 + END), 0) "voteDelta", + round(coalesce((sum( + CASE WHEN direction = 'UP' THEN + 1 + WHEN direction = 'DOWN' THEN + -1 + ELSE + 0 + END ) - 1) / (DATE_PART('hour', now() - max("Vote"."createdAt")) + 2) ^ 1.8 * 100000, -2147483648)::numeric, 0) AS "score", + rank() OVER (ORDER BY round(coalesce((sum( CASE WHEN direction = 'UP' THEN + 1 + WHEN direction = 'DOWN' THEN + -1 + ELSE + 0 + END) - 1) / (DATE_PART('hour', now() - max("Vote"."createdAt")) + 2) ^ 1.8 * 100000, -2147483648)::numeric, 0) + DESC, + "Post"."createdAt" DESC, + "Post".title ASC) "voteRank" + FROM + "Vote" + RIGHT JOIN "Post" ON "Vote"."postId" = "Post".id + GROUP BY + "Post".id, + "Vote"."postId" + ) + + UPDATE + public. "Post" + SET + "upVoteTotal" = r. "upVoteTotal", + "downVoteTotal" = r. "downVoteTotal", + "voteTotal" = r. "voteTotal", + "voteDelta" = r. "voteDelta", + "voteRank" = r. "voteRank", + "score" = r. "score" + FROM + r + WHERE + r."postId" = public. "Post".id; + + RETURN new; + END; + $$ language plpgsql security definer; + + CREATE TRIGGER on_vote_created AFTER INSERT ON public."Vote" FOR EACH ROW EXECUTE FUNCTION public.update_vote_counts(); + CREATE TRIGGER on_vote_deleted AFTER DELETE ON public."Vote" FOR EACH ROW EXECUTE FUNCTION public.update_vote_counts(); + ``` + 1. Views and Materialized Views + - Save it for later + - Views https://www.postgresql.org/docs/15/sql-createview.html + - Materialized Views are stored. Great for precalculating complex queries. Can be refreshed.- https://www.postgresql.org/docs/15/sql-creatematerializedview.html + 1. Prisma Nested Reads and Writes When to use [`connect`](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-an-existing-record), [`create` or `createMany`](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record) and [`connectOrCreate`](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-or-create-a-record). @@ -121,7 +206,7 @@ 1. Caching - No when to hold them ... when to walk way. when to ru. + - No when to hold them ... when to walk way. Know when to run. 1. Documentation diff --git a/README.md b/README.md index 1f899e52..bcb72517 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This repo is where these demos and examples live. - [2022-10-26-nested-writes-demo](2022-10-26-nested-writes-demo/README.md) - How To Perform Nested Writes with RedwoodJS and GraphQL - [2022-11-02-og-image-demo](2022-11-02-og-image-demo/README.md) - How to Generate OG Images for Social Cards using Netlify Edge Functions and RedwoodJS MetaTags - [2022-11-13-custom-md5-auth](2022-11-13-custom-md5-auth/README.md) - How to Implement Custom Auth in RedwoodJS v4 -- [2022-11-13-custom-md5-auth](2022-11-13-custom-md5-auth/README.md) - How to Implement Custom Auth in RedwoodJS v4 +- [2022-12-00-redwood-retro-lists](2022-12-00-redwood-retro-lists/README.md) - 2022 Redwood Year in Review. Top 10 Lists. Stats. Retrospectives. ## Discord Invite Link