Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into prod
Browse files Browse the repository at this point in the history
  • Loading branch information
sopyb committed Sep 14, 2023
2 parents 46d1cef + 5e6889a commit 2618f12
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 94 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "navigo-learn-api",
"version": "2.0.2",
"version": "2.0.3",
"description": "Navigo Learn API",
"repository": "https://github.com/NavigoLearn/API.git",
"author": "Navigo",
Expand Down
221 changes: 130 additions & 91 deletions src/util/Database/ExploreDB.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Database, { DatabaseConfig } from '@src/util/Database/DatabaseDriver';
import Database, {DatabaseConfig} from '@src/util/Database/DatabaseDriver';
import EnvVars from '@src/constants/EnvVars';
import {
SearchParameters,
} from '@src/middleware/validators/validateSearchParameters';
import { ResRoadmap } from '@src/types/response/ResRoadmap';
import {ResRoadmap} from '@src/types/response/ResRoadmap';
import {RoadmapTopic} from '@src/types/models/Roadmap';

// database credentials
const { DBCred } = EnvVars;
Expand All @@ -18,120 +19,158 @@ class ExploreDB extends Database {
super(config);
}

private static getIsLikedQuery(userid?: bigint): string {
return !!userid
? `SELECT COALESCE((SELECT value
FROM roadmapLikes
WHERE roadmapId = r.id
AND userId = ?
LIMIT 1), 0)`
: '0';
}

private static getTopicQuery(topic: string | string[]): string {
if (Array.isArray(topic)) {
return topic.map(() => '?').join(', ');
}
return '?';
}

private static getOrderByQuery(order: {
by: string;
direction: string;
}): string {
let query = '';
if (order.by === 't.likeCount') {
query = `CASE
WHEN t.likeCount < 0 THEN 3
WHEN t.likeCount = 0 THEN 2
ELSE 1
END ${order.direction}, `;
}

return `${query}${order.by} ${order.direction}`;
}

private static buildQueryParams(
userid: bigint | undefined,
search: string,
topic: RoadmapTopic | RoadmapTopic[],
page: number,
limit: number,
isCountQuery = false,
): unknown[] {
const params = [];

if (!isCountQuery) {
params.push(userid);
}

params.push(`%${search}%`, `%${search}%`);
params.push(Array.isArray(topic) ? topic.map((t) => t.toString()) : topic);

if (!isCountQuery) {
params.push((page - 1) * limit, limit);
}

return params;
}

public async getRoadmaps(
{ search, page, limit, topic, order }: SearchParameters,
userid?: bigint,
): Promise<ResRoadmapExplore> {
if (typeof search != 'string' || !page || !limit || !topic || !order)
return { result: [], totalRoadmaps: 0n };

const isLikeQuery = ExploreDB.getIsLikedQuery(userid);
const topicQuery = ExploreDB.getTopicQuery(topic);
const orderQuery = ExploreDB.getOrderByQuery(order);

const query = `
SELECT *
FROM (SELECT r.id as id,
r.name AS name,
r.description AS description,
r.topic AS topic,
r.isFeatured AS isFeatured,
r.isPublic AS isPublic,
r.isDraft AS isDraft,
r.createdAt AS createdAt,
r.updatedAt AS updatedAt,
u.id AS userId,
u.avatar AS userAvatar,
u.name AS userName,
(SELECT SUM(rl.value)
FROM roadmapLikes rl
WHERE roadmapId = r.id) AS likeCount,
(SELECT COUNT(*)
FROM roadmapViews
WHERE roadmapId = r.id) AS viewCount,
${
!!userid
? `(SELECT value FROM roadmapLikes
WHERE roadmapId = r.id
AND userId = ?
)
`
: '0'
} AS isLiked
FROM roadmaps r
INNER JOIN users u ON r.userId = u.id
WHERE (r.name LIKE ? OR r.description LIKE ?)
AND r.topic IN (${
Array.isArray(topic) ? topic.map(() => '?').join(', ') : '?'
})
AND r.isPublic = 1
AND r.isDraft = 0) as t
ORDER BY t.isFeatured DESC, ${
order.by === 't.likeCount'
? `CASE
WHEN t.likeCount < 0 THEN 3
WHEN t.likeCount = 0 THEN 2
ELSE 1
END,`
: ''
} ${order.by} ${order.direction}
LIMIT ?, ?
;
SELECT *
FROM (SELECT r.id as id,
r.name AS name,
r.description AS description,
r.topic AS topic,
r.isFeatured AS isFeatured,
r.isPublic AS isPublic,
r.isDraft AS isDraft,
r.createdAt AS createdAt,
r.updatedAt AS updatedAt,
u.id AS userId,
u.avatar AS userAvatar,
u.name AS userName,
(SELECT COALESCE(
(SELECT SUM(rl.value)
FROM roadmapLikes rl
WHERE roadmapId = r.id), 0)) AS likeCount,
(SELECT COUNT(*)
FROM roadmapViews
WHERE roadmapId = r.id) AS viewCount,
( ${isLikeQuery} ) AS isLiked
FROM roadmaps r
INNER JOIN users u ON r.userId = u.id
WHERE ( r.name LIKE ?
OR r.description LIKE ? )
AND r.topic IN ( ${topicQuery} )
AND r.isPublic = 1
AND r.isDraft = 0) as t
ORDER BY ${orderQuery}
LIMIT ?, ?;
`;
const query2 = `
SELECT count(*) AS result,
${
!!userid
? `(SELECT value FROM roadmapLikes
WHERE roadmapId = r.id
AND userId = ?
)`
: '0'
} AS isLiked
FROM roadmaps r
INNER JOIN users u ON r.userId = u.id
WHERE (r.name LIKE ? OR r.description LIKE ?)
AND r.topic IN (${
Array.isArray(topic) ? topic.map(() => '?').join(', ') : '?'
})
AND r.isPublic = 1
AND r.isDraft = 0;
const countQuery = `
SELECT count(*) AS result
FROM roadmaps r
INNER JOIN users u ON r.userId = u.id
WHERE ( r.name LIKE ? OR r.description LIKE ? )
AND r.topic IN ( ${topicQuery} )
AND r.isPublic = 1
AND r.isDraft = 0;
`;
const params = [];

if (!!userid) {
params.push(userid);
}
params.push(`%${search}%`);
params.push(`%${search}%`);
if (Array.isArray(topic)) topic.forEach((t) => params.push(t.toString()));
else params.push(topic);
params.push((page - 1) * limit);
params.push(limit);
const params = ExploreDB.buildQueryParams(
userid,
search,
topic,
page,
limit,
);

const countParams = ExploreDB.buildQueryParams(
userid,
search,
topic,
page,
limit,
true,
);

const result = await this.getQuery(query, params);
const result2 = await this.countQuery(query2, params.slice(0, -2));
const count = await this.countQuery(countQuery, countParams);

if (result === null) return { result: [], totalRoadmaps: 0n };
return {
result: result as unknown as ResRoadmap[],
totalRoadmaps: result2,
totalRoadmaps: count,
};
}

public async getRandomRoadmapId(): Promise<bigint | null> {
const query = `
SELECT id
FROM roadmaps
WHERE isPublic = 1
AND isDraft = 0
ORDER BY RAND()
LIMIT 1
SELECT id
FROM roadmaps
WHERE isPublic = 1
AND isDraft = 0
ORDER BY RAND()
LIMIT 1
`;

const result = await this.getQuery(query);

if (result === null)
return null;
if(result.length === 0)
return null;
if(result[0].id === null)
return null;
if (result === null) return null;
if (result.length === 0) return null;
if (result[0].id === null) return null;

return result[0].id as bigint;
}
Expand Down

0 comments on commit 2618f12

Please sign in to comment.