From ded91cbbf15ba6b232a3539648a29b1048ca4c58 Mon Sep 17 00:00:00 2001 From: Zakaria Mansouri Date: Thu, 2 Jan 2025 10:11:33 +0100 Subject: [PATCH] localized search endpoint --- api/src/search/controller.ts | 2 +- api/src/search/service.ts | 30 ++++++++++++++++++++++++++---- api/src/search/types.ts | 3 ++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/api/src/search/controller.ts b/api/src/search/controller.ts index cdcd10f9..7d9bc587 100644 --- a/api/src/search/controller.ts +++ b/api/src/search/controller.ts @@ -11,7 +11,7 @@ export class SearchController { @Get("/") public async search(@QueryParams() req: SearchQuery): Promise { - const searchResults = await this.searchService.search(req.query, req.limit); + const searchResults = await this.searchService.search(req.query, req.lang, req.limit); return { searchResults, }; diff --git a/api/src/search/service.ts b/api/src/search/service.ts index b2156b32..dd762603 100644 --- a/api/src/search/service.ts +++ b/api/src/search/service.ts @@ -5,6 +5,7 @@ import { ConfigService } from "src/config/service"; import { LoggerService } from "src/logger/service"; import { MeiliSearch } from "meilisearch"; import { Service } from "typedi"; +import { LanguageCode } from "@dzcode.io/utils/dist/language"; @Service() export class SearchService { @@ -25,20 +26,41 @@ export class SearchService { }); } - public search = async (q: string, limit?: number): Promise => { + public search = async (q: string, lang: LanguageCode, limit?: number): Promise => { + // TODO-ZM: only fetch Ids from search db, then query actually entities from their respective repositories this.logger.info({ message: `Searching for "${q}" in all indexes` }); const searchResults = await this.meilisearch.multiSearch({ queries: [ - { indexUid: "project", q, limit, attributesToRetrieve: ["id", "name"] }, + { indexUid: "project", q, limit, attributesToRetrieve: ["id", `name_${lang}`] }, { indexUid: "contribution", q, limit, - attributesToRetrieve: ["id", "title", "type", "activityCount", "url"], + attributesToRetrieve: ["id", `title_${lang}`, "type", "activityCount", "url"], + }, + { + indexUid: "contributor", + q, + limit, + attributesToRetrieve: ["id", `name_${lang}`, "avatarUrl"], }, - { indexUid: "contributor", q, limit, attributesToRetrieve: ["id", "name", "avatarUrl"] }, ], }); + + searchResults.results.forEach((result) => { + result.hits.forEach((hit) => { + if (hit[`name_${lang}`]) { + hit.name = hit[`name_${lang}`]; + delete hit[`name_${lang}`]; + } + + if (hit[`title_${lang}`]) { + hit.title = hit[`title_${lang}`]; + delete hit[`title_${lang}`]; + } + }); + }); + return searchResults as SearchResults; }; diff --git a/api/src/search/types.ts b/api/src/search/types.ts index e2b752e1..e9556032 100644 --- a/api/src/search/types.ts +++ b/api/src/search/types.ts @@ -4,8 +4,9 @@ import { GeneralResponse } from "src/app/types"; import { MultiSearchResponse } from "meilisearch"; import { ProjectEntity } from "@dzcode.io/models/dist/project"; import { IsNotEmpty, IsPositive, IsString } from "class-validator"; +import { LanguageQuery } from "src/_utils/language"; -export class SearchQuery { +export class SearchQuery extends LanguageQuery { @IsString() @IsNotEmpty() query!: string;