-
Couldn't load subscription status.
- Fork 0
Upgrade/refactor search module/chris #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
27dfb26
4f442f2
41b8806
cb9fd72
152fdce
b26ee02
61a25fd
1fd9d34
e7f8f3e
00e7a6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,63 +1,40 @@ | ||||||
| import { Request, Response } from "express"; | ||||||
| import SearchService from "../services/search.service"; | ||||||
| import { logger } from "../../../shared/utils/logger"; | ||||||
| import { searchType } from "../types"; | ||||||
|
|
||||||
|
|
||||||
| export class SearchController { | ||||||
| /** | ||||||
| * @description | ||||||
| * Fetches 5 users at a time where their username matches or starts with the text | ||||||
| * provided to the search query. If a starting point is provided, the search query | ||||||
| * starts from the provided starting point. | ||||||
| * Searches for users and/or content that matches the provided search text. | ||||||
| * | ||||||
| * @param req - Express request object. | ||||||
| * @param res - Express response object. | ||||||
| */ | ||||||
| static async searchUsers(req: Request, res: Response) { | ||||||
| static async search(req: Request, res: Response) { | ||||||
| const searchText = req.query.searchText as string; | ||||||
| const userStartingPoint = req.query.userStartingPoint as string; | ||||||
| const searchType = req.query.searchType as searchType; | ||||||
| const limit = parseInt(req.query.limit as string); | ||||||
| const offset = parseInt(req.query.offset as string); | ||||||
|
|
||||||
| logger.info(`Searching for users that match the following: ${searchText}`); | ||||||
| logger.info(`Searching for users and content that match the following: ${searchText}`); | ||||||
| try { | ||||||
| const response = await SearchService.searchUsers( | ||||||
| const response = await SearchService.search( | ||||||
| searchText, | ||||||
| userStartingPoint | ||||||
| searchType, | ||||||
| limit, | ||||||
| offset, | ||||||
| ); | ||||||
| res.status(200).json(response); | ||||||
| } catch (error) { | ||||||
| if (error instanceof Error) { | ||||||
| logger.error(`Error searching users: ${error.message}`); | ||||||
| logger.error(`Error searching for ${searchType}: ${error.message}`); | ||||||
| } else { | ||||||
| logger.error(`Error searching users: ${String(error)}`); | ||||||
| logger.error(`Error searching for ${searchType}: ${error}`); | ||||||
| } | ||||||
| res.status(500).json({ error: "Failed to search users" }); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @description | ||||||
| * Fetches 5 content items at a time where their title matches or starts with the | ||||||
| * text provided to the search query. | ||||||
| * | ||||||
| * @param req - Express request object. | ||||||
| * @param res - Express response object. | ||||||
| */ | ||||||
| static async searchContents(req: Request, res: Response) { | ||||||
| const searchText = req.query.searchText as string; | ||||||
| logger.info( | ||||||
| `Searching for content that matches the following: ${searchText}` | ||||||
| ); | ||||||
|
|
||||||
| try { | ||||||
| const response = await SearchService.searchContents(searchText); | ||||||
| res.status(200).json(response); | ||||||
| } catch (error) { | ||||||
| if (error instanceof Error) { | ||||||
| logger.error(`Error searching content: ${error.message}`); | ||||||
| } else { | ||||||
| logger.error(`Error searching content: ${String(error)}`); | ||||||
| } | ||||||
| res.status(500).json({ error: "Failed to search content" }); | ||||||
| res.status(500).json({error: "Failed to search users"}); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update error message to be generic. The error message is still specific to users but should reflect the unified search functionality. - res.status(500).json({error: "Failed to search users"});
+ res.status(500).json({error: "Failed to perform search"});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import { logger } from "../../../shared/utils/logger"; | ||
| import { query } from '../../../shared/database/postgres.connector'; | ||
| import { User, Content } from '../types'; | ||
|
|
||
| /** | ||
| * Searches the 'users' table for a username. | ||
| */ | ||
| export async function findUsers(searchText: string, limit: number, offset: number): Promise<User[]> { | ||
| const sql = ` | ||
| SELECT | ||
| user_id, | ||
| username, | ||
| first_name, | ||
| last_name, | ||
| profile_image | ||
| FROM users | ||
| WHERE | ||
| username ILIKE $1 OR | ||
| first_name ILIKE $1 OR | ||
| last_name ILIKE $1 | ||
| ORDER BY first_name, last_name | ||
| LIMIT $2 OFFSET $3; | ||
| `; | ||
| const params = [`%${searchText}%`, limit, offset]; | ||
|
|
||
| try { | ||
| const result = await query(sql, params); | ||
| return result.rows; | ||
| } catch (err) { | ||
| logger.error('Error executing user search query:', err); | ||
| throw new Error('Database query for users failed.'); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Searches the 'content' table. | ||
| * It uses the 'summary' column for the preview and searches title and content body. | ||
| */ | ||
| export async function findContent(searchText: string, limit: number, offset: number): Promise<Content[]> { | ||
| const sql = ` | ||
| SELECT | ||
| c.content_id, | ||
| u.username, | ||
| u.first_name, | ||
| u.last_name, | ||
| u.profile_image, | ||
| c.title, | ||
| COALESCE(c.summary, LEFT(c.content, 150)) as summary, | ||
| c.date_created | ||
| FROM content c | ||
| JOIN users u ON c.creator_id = u.user_id | ||
| WHERE c.title ILIKE $1 OR c.content ILIKE $1 | ||
| ORDER BY c.date_created DESC | ||
| LIMIT $2 OFFSET $3; | ||
| `; | ||
| const params = [`%${searchText}%`, limit, offset]; | ||
|
|
||
| try { | ||
| const result = await query(sql, params); | ||
| return result.rows; | ||
| } catch (err) { | ||
| logger.error('Error executing content search query:', err); | ||
| throw new Error('Database query for content failed.'); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './search.types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for numeric parameters.
The
limitandoffsetparameters should be validated to ensure they are valid numbers and within reasonable bounds.📝 Committable suggestion
🤖 Prompt for AI Agents