feat(search): implement Search module with Typesense full-text & geo search
- TypesenseClient service with configurable connection - Collection schema for listings with facets, geo-point, and Vietnamese text - ListingIndexer service with PostGIS coordinate extraction for geo search - CQRS commands: SyncListing, ReindexAll (batch with pagination) - CQRS queries: SearchProperties (filters, sorting), GeoSearch (radius) - Event handlers for listing.approved/updated/deactivated auto-sync - REST endpoints: GET /search, GET /search/geo, POST /search/reindex (admin) - DTOs with class-validator validation and pagination Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export { ListingApprovedEventHandler } from './listing-approved.handler';
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { LoggerService } from '@modules/shared/infrastructure/logger.service';
|
||||
import { ListingIndexerService } from '../services/listing-indexer.service';
|
||||
|
||||
@Injectable()
|
||||
export class ListingApprovedEventHandler {
|
||||
constructor(
|
||||
private readonly indexer: ListingIndexerService,
|
||||
private readonly logger: LoggerService,
|
||||
) {}
|
||||
|
||||
@OnEvent('listing.approved')
|
||||
async handle(payload: { listingId: string }): Promise<void> {
|
||||
this.logger.log(`Handling listing.approved for ${payload.listingId}`, 'ListingApprovedHandler');
|
||||
await this.indexer.indexListing(payload.listingId);
|
||||
}
|
||||
|
||||
@OnEvent('listing.updated')
|
||||
async handleUpdate(payload: { listingId: string }): Promise<void> {
|
||||
this.logger.log(`Handling listing.updated for ${payload.listingId}`, 'ListingApprovedHandler');
|
||||
await this.indexer.indexListing(payload.listingId);
|
||||
}
|
||||
|
||||
@OnEvent('listing.deactivated')
|
||||
async handleDeactivation(payload: { listingId: string }): Promise<void> {
|
||||
this.logger.log(`Handling listing.deactivated for ${payload.listingId}`, 'ListingApprovedHandler');
|
||||
await this.indexer.removeListing(payload.listingId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user