1- import Database , { DatabaseConfig } from '@src/util/Database/DatabaseDriver' ;
1+ import Database , { DatabaseConfig } from '@src/util/Database/DatabaseDriver' ;
22import EnvVars from '@src/constants/EnvVars' ;
33import {
44 SearchParameters ,
55} from '@src/middleware/validators/validateSearchParameters' ;
6- import { ResRoadmap } from '@src/types/response/ResRoadmap' ;
6+ import { ResRoadmap } from '@src/types/response/ResRoadmap' ;
7+ import { RoadmapTopic } from '@src/types/models/Roadmap' ;
78
89// database credentials
910const { DBCred } = EnvVars ;
@@ -18,120 +19,158 @@ class ExploreDB extends Database {
1819 super ( config ) ;
1920 }
2021
22+ private static getIsLikedQuery ( userid ?: bigint ) : string {
23+ return ! ! userid
24+ ? `SELECT COALESCE((SELECT value
25+ FROM roadmapLikes
26+ WHERE roadmapId = r.id
27+ AND userId = ?
28+ LIMIT 1), 0)`
29+ : '0' ;
30+ }
31+
32+ private static getTopicQuery ( topic : string | string [ ] ) : string {
33+ if ( Array . isArray ( topic ) ) {
34+ return topic . map ( ( ) => '?' ) . join ( ', ' ) ;
35+ }
36+ return '?' ;
37+ }
38+
39+ private static getOrderByQuery ( order : {
40+ by : string ;
41+ direction : string ;
42+ } ) : string {
43+ let query = '' ;
44+ if ( order . by === 't.likeCount' ) {
45+ query = `CASE
46+ WHEN t.likeCount < 0 THEN 3
47+ WHEN t.likeCount = 0 THEN 2
48+ ELSE 1
49+ END ${ order . direction } , ` ;
50+ }
51+
52+ return `${ query } ${ order . by } ${ order . direction } ` ;
53+ }
54+
55+ private static buildQueryParams (
56+ userid : bigint | undefined ,
57+ search : string ,
58+ topic : RoadmapTopic | RoadmapTopic [ ] ,
59+ page : number ,
60+ limit : number ,
61+ isCountQuery = false ,
62+ ) : unknown [ ] {
63+ const params = [ ] ;
64+
65+ if ( ! isCountQuery ) {
66+ params . push ( userid ) ;
67+ }
68+
69+ params . push ( `%${ search } %` , `%${ search } %` ) ;
70+ params . push ( Array . isArray ( topic ) ? topic . map ( ( t ) => t . toString ( ) ) : topic ) ;
71+
72+ if ( ! isCountQuery ) {
73+ params . push ( ( page - 1 ) * limit , limit ) ;
74+ }
75+
76+ return params ;
77+ }
78+
2179 public async getRoadmaps (
2280 { search, page, limit, topic, order } : SearchParameters ,
2381 userid ?: bigint ,
2482 ) : Promise < ResRoadmapExplore > {
2583 if ( typeof search != 'string' || ! page || ! limit || ! topic || ! order )
2684 return { result : [ ] , totalRoadmaps : 0n } ;
85+
86+ const isLikeQuery = ExploreDB . getIsLikedQuery ( userid ) ;
87+ const topicQuery = ExploreDB . getTopicQuery ( topic ) ;
88+ const orderQuery = ExploreDB . getOrderByQuery ( order ) ;
89+
2790 const query = `
28- SELECT *
29- FROM (SELECT r.id as id,
30- r.name AS name,
31- r.description AS description,
32- r.topic AS topic,
33- r.isFeatured AS isFeatured,
34- r.isPublic AS isPublic,
35- r.isDraft AS isDraft,
36- r.createdAt AS createdAt,
37- r.updatedAt AS updatedAt,
38- u.id AS userId,
39- u.avatar AS userAvatar,
40- u.name AS userName,
41- (SELECT SUM(rl.value)
42- FROM roadmapLikes rl
43- WHERE roadmapId = r.id) AS likeCount,
44- (SELECT COUNT(*)
45- FROM roadmapViews
46- WHERE roadmapId = r.id) AS viewCount,
47- ${
48- ! ! userid
49- ? `(SELECT value FROM roadmapLikes
50- WHERE roadmapId = r.id
51- AND userId = ?
52- )
53- `
54- : '0'
55- } AS isLiked
56- FROM roadmaps r
57- INNER JOIN users u ON r.userId = u.id
58- WHERE (r.name LIKE ? OR r.description LIKE ?)
59- AND r.topic IN (${
60- Array . isArray ( topic ) ? topic . map ( ( ) => '?' ) . join ( ', ' ) : '?'
61- } )
62- AND r.isPublic = 1
63- AND r.isDraft = 0) as t
64- ORDER BY t.isFeatured DESC, ${
65- order . by === 't.likeCount'
66- ? `CASE
67- WHEN t.likeCount < 0 THEN 3
68- WHEN t.likeCount = 0 THEN 2
69- ELSE 1
70- END,`
71- : ''
72- } ${ order . by } ${ order . direction }
73- LIMIT ?, ?
74- ;
91+ SELECT *
92+ FROM (SELECT r.id as id,
93+ r.name AS name,
94+ r.description AS description,
95+ r.topic AS topic,
96+ r.isFeatured AS isFeatured,
97+ r.isPublic AS isPublic,
98+ r.isDraft AS isDraft,
99+ r.createdAt AS createdAt,
100+ r.updatedAt AS updatedAt,
101+ u.id AS userId,
102+ u.avatar AS userAvatar,
103+ u.name AS userName,
104+ (SELECT COALESCE(
105+ (SELECT SUM(rl.value)
106+ FROM roadmapLikes rl
107+ WHERE roadmapId = r.id), 0)) AS likeCount,
108+ (SELECT COUNT(*)
109+ FROM roadmapViews
110+ WHERE roadmapId = r.id) AS viewCount,
111+ ( ${ isLikeQuery } ) AS isLiked
112+ FROM roadmaps r
113+ INNER JOIN users u ON r.userId = u.id
114+ WHERE ( r.name LIKE ?
115+ OR r.description LIKE ? )
116+ AND r.topic IN ( ${ topicQuery } )
117+ AND r.isPublic = 1
118+ AND r.isDraft = 0) as t
119+ ORDER BY ${ orderQuery }
120+ LIMIT ?, ?;
75121 ` ;
76- const query2 = `
77- SELECT count(*) AS result,
78- ${
79- ! ! userid
80- ? `(SELECT value FROM roadmapLikes
81- WHERE roadmapId = r.id
82- AND userId = ?
83- )`
84- : '0'
85- } AS isLiked
86- FROM roadmaps r
87- INNER JOIN users u ON r.userId = u.id
88- WHERE (r.name LIKE ? OR r.description LIKE ?)
89- AND r.topic IN (${
90- Array . isArray ( topic ) ? topic . map ( ( ) => '?' ) . join ( ', ' ) : '?'
91- } )
92- AND r.isPublic = 1
93- AND r.isDraft = 0;
122+ const countQuery = `
123+ SELECT count(*) AS result
124+ FROM roadmaps r
125+ INNER JOIN users u ON r.userId = u.id
126+ WHERE ( r.name LIKE ? OR r.description LIKE ? )
127+ AND r.topic IN ( ${ topicQuery } )
128+ AND r.isPublic = 1
129+ AND r.isDraft = 0;
94130 ` ;
95- const params = [ ] ;
96131
97- if ( ! ! userid ) {
98- params . push ( userid ) ;
99- }
100- params . push ( `%${ search } %` ) ;
101- params . push ( `%${ search } %` ) ;
102- if ( Array . isArray ( topic ) ) topic . forEach ( ( t ) => params . push ( t . toString ( ) ) ) ;
103- else params . push ( topic ) ;
104- params . push ( ( page - 1 ) * limit ) ;
105- params . push ( limit ) ;
132+ const params = ExploreDB . buildQueryParams (
133+ userid ,
134+ search ,
135+ topic ,
136+ page ,
137+ limit ,
138+ ) ;
139+
140+ const countParams = ExploreDB . buildQueryParams (
141+ userid ,
142+ search ,
143+ topic ,
144+ page ,
145+ limit ,
146+ true ,
147+ ) ;
106148
107149 const result = await this . getQuery ( query , params ) ;
108- const result2 = await this . countQuery ( query2 , params . slice ( 0 , - 2 ) ) ;
150+ const count = await this . countQuery ( countQuery , countParams ) ;
109151
110152 if ( result === null ) return { result : [ ] , totalRoadmaps : 0n } ;
111153 return {
112154 result : result as unknown as ResRoadmap [ ] ,
113- totalRoadmaps : result2 ,
155+ totalRoadmaps : count ,
114156 } ;
115157 }
116158
117159 public async getRandomRoadmapId ( ) : Promise < bigint | null > {
118160 const query = `
119- SELECT id
120- FROM roadmaps
121- WHERE isPublic = 1
122- AND isDraft = 0
123- ORDER BY RAND()
124- LIMIT 1
161+ SELECT id
162+ FROM roadmaps
163+ WHERE isPublic = 1
164+ AND isDraft = 0
165+ ORDER BY RAND()
166+ LIMIT 1
125167 ` ;
126168
127169 const result = await this . getQuery ( query ) ;
128170
129- if ( result === null )
130- return null ;
131- if ( result . length === 0 )
132- return null ;
133- if ( result [ 0 ] . id === null )
134- return null ;
171+ if ( result === null ) return null ;
172+ if ( result . length === 0 ) return null ;
173+ if ( result [ 0 ] . id === null ) return null ;
135174
136175 return result [ 0 ] . id as bigint ;
137176 }
0 commit comments