From 8b0904a40e6e2dcd00389da22d74422e16644a55 Mon Sep 17 00:00:00 2001 From: LaGodxy <83363896+LaGodxy@users.noreply.github.com> Date: Sat, 25 Apr 2026 00:28:03 -0700 Subject: [PATCH] Revert "feat(search): implement PostgreSQL full-text search with ranking" --- prisma/schema.prisma | 7 ----- src/email/email.service.ts | 11 -------- src/search/search.controller.ts | 16 ------------ src/search/search.service.ts | 46 +++++++++++---------------------- 4 files changed, 15 insertions(+), 65 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 15d06b21..40e27858 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -602,10 +602,3 @@ model SearchSuggestion { @@index([expiresAt]) @@map("search_suggestions") } - -model Project { - id String @id @default(uuid()) - title String - description String - @@index([title, description], type: FullText) -} diff --git a/src/email/email.service.ts b/src/email/email.service.ts index 6cf8049e..4a8f08ef 100644 --- a/src/email/email.service.ts +++ b/src/email/email.service.ts @@ -142,14 +142,3 @@ Summary: ${payload.description} // }); } } - -async sendEmail(userId: string, subject: string, body: string) { - const unsubscribeLink = `${process.env.APP_URL}/unsubscribe?userId=${userId}`; - const footer = `\n\nIf you no longer wish to receive these emails, click here to unsubscribe: ${unsubscribeLink}`; - - await this.mailer.sendMail({ - to: userId, - subject, - text: body + footer, - }); -} diff --git a/src/search/search.controller.ts b/src/search/search.controller.ts index 3114877e..0ef361c1 100644 --- a/src/search/search.controller.ts +++ b/src/search/search.controller.ts @@ -24,14 +24,6 @@ export class SearchController { return this.searchService.searchProperties(req.user.id, searchQuery); } - @Get('projects') - @ApiOperation({ summary: 'Full-text search for projects' }) - @ApiQuery({ name: 'q', required: true, description: 'Search query' }) - @ApiResponse({ status: 200, description: 'Project search results returned successfully' }) - async searchProjects(@Query('q') query: string, @Query() filters: any) { - return this.searchService.searchProjects(query, filters); - } - @Get('suggestions') @ApiOperation({ summary: 'Get search autocomplete suggestions' }) @ApiQuery({ name: 'q', required: false, description: 'Search query' }) @@ -40,14 +32,6 @@ export class SearchController { return this.searchService.getSuggestions(query || ''); } - @Get('terms') - @ApiOperation({ summary: 'Get full-text search term suggestions' }) - @ApiQuery({ name: 'q', required: true, description: 'Search query prefix' }) - @ApiResponse({ status: 200, description: 'Search term suggestions returned successfully' }) - async suggestTerms(@Query('q') query: string) { - return this.searchService.suggestTerms(query); - } - @Get('filters/saved') @ApiOperation({ summary: 'Get user\'s saved filters' }) @ApiResponse({ status: 200, description: 'Saved filters returned successfully' }) diff --git a/src/search/search.service.ts b/src/search/search.service.ts index b65b9157..cef7c4eb 100644 --- a/src/search/search.service.ts +++ b/src/search/search.service.ts @@ -56,8 +56,10 @@ export class SearchService { const queryId = await this.analyticsService.recordSearch(userId, searchQuery); try { + // Build base query let whereClause: any = {}; + // Apply text search if (searchQuery.query) { whereClause.OR = [ { title: { contains: searchQuery.query, mode: 'insensitive' } }, @@ -68,6 +70,7 @@ export class SearchService { ]; } + // Apply geographic filters if (searchQuery.geographic) { whereClause = await this.geographicService.applyGeographicFilter( whereClause, @@ -75,6 +78,7 @@ export class SearchService { ); } + // Apply advanced filters if (searchQuery.filters) { whereClause = await this.filtersService.applyFilters( whereClause, @@ -82,18 +86,15 @@ export class SearchService { ); } + // Execute query with sorting and pagination const { page = 1, limit = 20 } = searchQuery.pagination || {}; const { field = 'createdAt', order = 'desc' } = searchQuery.sort || {}; - const items: any[] = await this.prisma.property.findMany({ - where: whereClause, - orderBy: { [field]: order }, - skip: (page - 1) * limit, - take: limit, - }); - - const total = await this.prisma.property.count({ where: whereClause }); + // Mock data for now - this would typically query the database + const items: any[] = []; + const total = 0; + // Generate facets const facets = await this.facetsService.buildFacets(items, [ 'propertyType', 'status', @@ -103,15 +104,17 @@ export class SearchService { 'bathrooms', ]); + // Get suggestions const suggestions = await this.autocompleteService.getSuggestions( searchQuery.query || '', ); + // Record search history if (searchQuery.query) { this.historyService.record(userId, searchQuery.query); } - return { + const result: SearchResult = { items, total, facets, @@ -121,34 +124,14 @@ export class SearchService { took: Date.now() - startTime, }, }; + + return result; } catch (error) { await this.analyticsService.recordSearchError(queryId, error); throw error; } } - // PostgreSQL full-text search for projects - async searchProjects(query: string, filters?: any) { - return this.prisma.$queryRaw` - SELECT id, title, description, - ts_rank_cd(to_tsvector('english', title || ' ' || description), plainto_tsquery(${query})) AS rank - FROM "Project" - WHERE to_tsvector('english', title || ' ' || description) @@ plainto_tsquery(${query}) - ORDER BY rank DESC - LIMIT 20; - `; - } - - async suggestTerms(query: string) { - return this.prisma.$queryRaw` - SELECT word - FROM ts_stat('SELECT to_tsvector(''english'', title || '' '' || description) FROM "Project"') - WHERE word LIKE ${query || ''} || '%' - ORDER BY nentry DESC - LIMIT 5; - `; - } - async getSuggestions(query: string): Promise { return this.autocompleteService.getSuggestions(query); } @@ -168,4 +151,5 @@ export class SearchService { async getPopularSearches(): Promise { return this.analyticsService.getPopularSearches(); } + }