@@ -5,7 +5,13 @@ import { DBError } from '@/exception';
55export class PostRepository {
66 constructor ( private pool : Pool ) { }
77
8- async findPostsByUserId ( userId : number , cursor ?: string , sort ?: string , isAsc ?: boolean , limit : number = 15 ) {
8+ async findPostsByUserId (
9+ userId : number ,
10+ cursor ?: string ,
11+ sort ?: string ,
12+ isAsc : boolean = false ,
13+ limit : number = 15
14+ ) {
915 try {
1016 // 1) 정렬 컬럼 매핑
1117 let sortCol = 'p.released_at' ;
@@ -62,10 +68,7 @@ export class PostRepository {
6268 pds.date
6369 FROM posts_post p
6470 LEFT JOIN (
65- SELECT post_id,
66- daily_view_count,
67- daily_like_count,
68- date
71+ SELECT post_id, daily_view_count, daily_like_count, date
6972 FROM posts_postdailystatistics
7073 WHERE (date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date = (NOW() AT TIME ZONE 'UTC')::date
7174 ) pds ON p.id = pds.post_id
@@ -116,6 +119,98 @@ export class PostRepository {
116119 }
117120 }
118121
122+ // findPostsByUserId 와 동일
123+ // view_growth, like_growth 컬럼 추가 연산
124+ async findPostsByUserIdWithGrowthMetrics (
125+ userId : number ,
126+ cursor ?: string ,
127+ isAsc : boolean = false ,
128+ limit : number = 15
129+ ) {
130+ try {
131+ const selectFields = `
132+ p.id,
133+ p.title,
134+ p.slug,
135+ p.created_at AS post_created_at,
136+ p.released_at AS post_released_at,
137+ COALESCE(pds.daily_view_count, 0) AS daily_view_count,
138+ COALESCE(pds.daily_like_count, 0) AS daily_like_count,
139+ COALESCE(yesterday_stats.daily_view_count, 0) AS yesterday_daily_view_count,
140+ COALESCE(yesterday_stats.daily_like_count, 0) AS yesterday_daily_like_count,
141+ pds.date,
142+ (COALESCE(pds.daily_view_count, 0) - COALESCE(yesterday_stats.daily_view_count, 0)) AS view_growth,
143+ (COALESCE(pds.daily_like_count, 0) - COALESCE(yesterday_stats.daily_like_count, 0)) AS like_growth
144+ ` ;
145+
146+ const direction = isAsc ? 'ASC' : 'DESC' ;
147+ const orderByExpression = `view_growth ${ direction } , p.id ${ direction } ` ;
148+
149+ // 커서 처리
150+ let cursorCondition = '' ;
151+ let params : unknown [ ] = [ ] ;
152+
153+ if ( cursor ) {
154+ const [ cursorSortValue , cursorId ] = cursor . split ( ',' ) ;
155+
156+ cursorCondition = `
157+ AND (
158+ (COALESCE(pds.daily_view_count, 0) - COALESCE(yesterday_stats.daily_view_count, 0)) ${ isAsc ? '>' : '<' } $2
159+ OR (
160+ (COALESCE(pds.daily_view_count, 0) - COALESCE(yesterday_stats.daily_view_count, 0)) = $2
161+ AND p.id ${ isAsc ? '>' : '<' } $3
162+ )
163+ )
164+ ` ;
165+
166+ params = [ userId , cursorSortValue , cursorId , limit ] ;
167+ } else {
168+ params = [ userId , limit ] ;
169+ }
170+
171+ const query = `
172+ SELECT ${ selectFields }
173+ FROM posts_post p
174+ LEFT JOIN (
175+ SELECT post_id, daily_view_count, daily_like_count, date
176+ FROM posts_postdailystatistics
177+ WHERE (date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date = (NOW() AT TIME ZONE 'UTC')::date
178+ ) pds ON p.id = pds.post_id
179+ LEFT JOIN (
180+ SELECT post_id, daily_view_count, daily_like_count, date
181+ FROM posts_postdailystatistics
182+ WHERE (date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date = (NOW() AT TIME ZONE 'UTC' - INTERVAL '1 day')::date
183+ ) yesterday_stats ON p.id = yesterday_stats.post_id
184+ WHERE p.user_id = $1
185+ AND (pds.post_id IS NOT NULL OR yesterday_stats.post_id IS NOT NULL)
186+ ${ cursorCondition }
187+ ORDER BY ${ orderByExpression }
188+ LIMIT ${ cursor ? '$4' : '$2' }
189+ ` ;
190+
191+ const posts = await this . pool . query ( query , params ) ;
192+
193+ if ( posts . rows . length === 0 ) {
194+ return {
195+ posts : [ ] ,
196+ nextCursor : null ,
197+ } ;
198+ }
199+
200+ // 다음 커서 생성
201+ const lastPost = posts . rows [ posts . rows . length - 1 ] ;
202+ const nextCursor = `${ lastPost . view_growth } ,${ lastPost . id } ` ;
203+
204+ return {
205+ posts : posts . rows ,
206+ nextCursor,
207+ } ;
208+ } catch ( error ) {
209+ logger . error ( 'Post Repo findPostsByUserIdWithGrowthMetrics error: ' , error ) ;
210+ throw new DBError ( '트래픽 성장률 기준 post 조회 중 문제가 발생했습니다.' ) ;
211+ }
212+ }
213+
119214 async getTotalPostCounts ( id : number ) {
120215 try {
121216 const query = 'SELECT COUNT(*) FROM "posts_post" WHERE user_id = $1' ;
0 commit comments