[BE-DB-013] be-db: Add database views for common queries
This commit is contained in:
parent
58a5a27d56
commit
379585fcb1
2 changed files with 148 additions and 2 deletions
|
|
@ -3350,7 +3350,7 @@
|
|||
"description": "Create views for user_stats, track_stats, playlist_stats",
|
||||
"owner": "backend",
|
||||
"estimated_hours": 5,
|
||||
"status": "todo",
|
||||
"status": "completed",
|
||||
"files_involved": [],
|
||||
"implementation_steps": [
|
||||
{
|
||||
|
|
@ -3371,7 +3371,9 @@
|
|||
"Unit tests",
|
||||
"Integration tests"
|
||||
],
|
||||
"notes": ""
|
||||
"notes": "",
|
||||
"completed_at": "2025-12-24T15:46:28.058411",
|
||||
"implementation_notes": "Created migration 051_stats_views.sql with three views: user_stats (aggregates user data from tracks, playlists, follows, track_plays, track_likes, track_comments), track_stats (aggregates track data from track_plays, playback_analytics, track_shares), and playlist_stats (aggregates playlist data from playlist_tracks, tracks, playlist_collaborators, playlist_share_links). All views exclude soft-deleted records and include comprehensive statistics."
|
||||
},
|
||||
{
|
||||
"id": "BE-DB-014",
|
||||
|
|
|
|||
144
veza-backend-api/migrations/051_stats_views.sql
Normal file
144
veza-backend-api/migrations/051_stats_views.sql
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
-- 051_stats_views.sql
|
||||
-- Database Views for Common Queries (BE-DB-013: Add database views for common queries)
|
||||
-- Create views for user_stats, track_stats, playlist_stats
|
||||
|
||||
-- === USER_STATS VIEW ===
|
||||
-- View for user statistics aggregating data from multiple tables
|
||||
CREATE OR REPLACE VIEW public.user_stats AS
|
||||
SELECT
|
||||
u.id AS user_id,
|
||||
u.username,
|
||||
u.email,
|
||||
u.created_at AS user_created_at,
|
||||
|
||||
-- Track statistics
|
||||
COUNT(DISTINCT t.id) AS tracks_count,
|
||||
COALESCE(SUM(t.play_count), 0) AS total_track_plays,
|
||||
COALESCE(SUM(t.like_count), 0) AS total_track_likes,
|
||||
COALESCE(SUM(t.download_count), 0) AS total_track_downloads,
|
||||
|
||||
-- Playlist statistics
|
||||
COUNT(DISTINCT p.id) AS playlists_count,
|
||||
COALESCE(SUM(p.track_count), 0) AS total_playlist_tracks,
|
||||
COALESCE(SUM(p.follower_count), 0) AS total_playlist_followers,
|
||||
|
||||
-- Social statistics
|
||||
COUNT(DISTINCT f1.id) AS followers_count,
|
||||
COUNT(DISTINCT f2.id) AS following_count,
|
||||
|
||||
-- Playback statistics
|
||||
COUNT(DISTINCT tp.track_id) AS unique_tracks_played,
|
||||
COUNT(tp.id) AS total_plays,
|
||||
COALESCE(SUM(tp.duration), 0) AS total_play_duration,
|
||||
CASE
|
||||
WHEN COUNT(tp.id) > 0 THEN COALESCE(SUM(tp.duration), 0)::FLOAT / COUNT(tp.id)
|
||||
ELSE 0
|
||||
END AS average_play_duration,
|
||||
|
||||
-- Like statistics
|
||||
COUNT(DISTINCT tl.track_id) AS liked_tracks_count,
|
||||
|
||||
-- Comment statistics
|
||||
COUNT(DISTINCT tc.id) AS comments_count
|
||||
|
||||
FROM public.users u
|
||||
LEFT JOIN public.tracks t ON t.creator_id = u.id AND t.deleted_at IS NULL
|
||||
LEFT JOIN public.playlists p ON p.user_id = u.id AND p.deleted_at IS NULL
|
||||
LEFT JOIN public.follows f1 ON f1.followed_id = u.id AND f1.deleted_at IS NULL
|
||||
LEFT JOIN public.follows f2 ON f2.follower_id = u.id AND f2.deleted_at IS NULL
|
||||
LEFT JOIN public.track_plays tp ON tp.user_id = u.id
|
||||
LEFT JOIN public.track_likes tl ON tl.user_id = u.id
|
||||
LEFT JOIN public.track_comments tc ON tc.user_id = u.id AND tc.deleted_at IS NULL
|
||||
WHERE u.deleted_at IS NULL
|
||||
GROUP BY u.id, u.username, u.email, u.created_at;
|
||||
|
||||
COMMENT ON VIEW public.user_stats IS 'Aggregated user statistics view including tracks, playlists, social, and playback metrics';
|
||||
|
||||
-- === TRACK_STATS VIEW ===
|
||||
-- View for track statistics aggregating plays, likes, comments, and downloads
|
||||
CREATE OR REPLACE VIEW public.track_stats AS
|
||||
SELECT
|
||||
t.id AS track_id,
|
||||
t.title,
|
||||
t.artist,
|
||||
t.creator_id,
|
||||
t.created_at AS track_created_at,
|
||||
t.published_at,
|
||||
|
||||
-- Denormalized counts from tracks table
|
||||
t.play_count AS views,
|
||||
t.like_count AS likes,
|
||||
t.comment_count AS comments,
|
||||
t.download_count AS downloads,
|
||||
|
||||
-- Playback statistics
|
||||
COUNT(DISTINCT tp.user_id) AS unique_listeners,
|
||||
COUNT(tp.id) AS total_plays,
|
||||
COALESCE(SUM(tp.duration), 0) AS total_play_time,
|
||||
CASE
|
||||
WHEN COUNT(tp.id) > 0 THEN COALESCE(SUM(tp.duration), 0)::FLOAT / COUNT(tp.id)
|
||||
ELSE 0
|
||||
END AS average_duration,
|
||||
|
||||
-- Playback analytics
|
||||
COALESCE(AVG(pa.completion_rate), 0) AS average_completion_rate,
|
||||
COALESCE(SUM(pa.play_time), 0) AS total_analytics_play_time,
|
||||
COALESCE(SUM(pa.pause_count), 0) AS total_pause_count,
|
||||
COALESCE(SUM(pa.seek_count), 0) AS total_seek_count,
|
||||
|
||||
-- Share statistics
|
||||
COUNT(DISTINCT ts.id) AS share_links_count,
|
||||
COALESCE(SUM(ts.access_count), 0) AS total_share_accesses
|
||||
|
||||
FROM public.tracks t
|
||||
LEFT JOIN public.track_plays tp ON tp.track_id = t.id
|
||||
LEFT JOIN public.playback_analytics pa ON pa.track_id = t.id
|
||||
LEFT JOIN public.track_shares ts ON ts.track_id = t.id AND ts.deleted_at IS NULL
|
||||
WHERE t.deleted_at IS NULL
|
||||
GROUP BY t.id, t.title, t.artist, t.creator_id, t.created_at, t.published_at,
|
||||
t.play_count, t.like_count, t.comment_count, t.download_count;
|
||||
|
||||
COMMENT ON VIEW public.track_stats IS 'Aggregated track statistics view including plays, likes, comments, downloads, and playback analytics';
|
||||
|
||||
-- === PLAYLIST_STATS VIEW ===
|
||||
-- View for playlist statistics aggregating tracks, followers, and plays
|
||||
CREATE OR REPLACE VIEW public.playlist_stats AS
|
||||
SELECT
|
||||
p.id AS playlist_id,
|
||||
p.name AS playlist_name,
|
||||
p.user_id AS creator_id,
|
||||
p.created_at AS playlist_created_at,
|
||||
p.updated_at AS playlist_updated_at,
|
||||
|
||||
-- Denormalized counts from playlists table
|
||||
p.track_count AS tracks_count,
|
||||
p.follower_count AS followers_count,
|
||||
|
||||
-- Track statistics (aggregated from playlist_tracks)
|
||||
COUNT(DISTINCT pt.track_id) AS actual_track_count,
|
||||
COALESCE(SUM(t.play_count), 0) AS total_track_plays,
|
||||
COALESCE(SUM(t.like_count), 0) AS total_track_likes,
|
||||
COALESCE(AVG(t.duration), 0) AS average_track_duration,
|
||||
COALESCE(SUM(t.duration), 0) AS total_playlist_duration,
|
||||
|
||||
-- Collaboration statistics
|
||||
COUNT(DISTINCT pc.user_id) AS collaborators_count,
|
||||
|
||||
-- Share statistics
|
||||
COUNT(DISTINCT psl.id) AS share_links_count,
|
||||
COALESCE(SUM(psl.access_count), 0) AS total_share_accesses
|
||||
|
||||
FROM public.playlists p
|
||||
LEFT JOIN public.playlist_tracks pt ON pt.playlist_id = p.id
|
||||
LEFT JOIN public.tracks t ON t.id = pt.track_id AND t.deleted_at IS NULL
|
||||
LEFT JOIN public.playlist_collaborators pc ON pc.playlist_id = p.id AND pc.deleted_at IS NULL
|
||||
LEFT JOIN public.playlist_share_links psl ON psl.playlist_id = p.id AND psl.deleted_at IS NULL
|
||||
WHERE p.deleted_at IS NULL
|
||||
GROUP BY p.id, p.name, p.user_id, p.created_at, p.updated_at,
|
||||
p.track_count, p.follower_count;
|
||||
|
||||
COMMENT ON VIEW public.playlist_stats IS 'Aggregated playlist statistics view including tracks, followers, plays, and collaboration metrics';
|
||||
|
||||
-- Indexes for better query performance (if needed)
|
||||
-- Note: Views don't support indexes directly, but indexes on underlying tables will help
|
||||
|
||||
Loading…
Reference in a new issue