import { HttpService } from "@nestjs/axios"; import { GatewayTimeoutException, ImATeapotException, Injectable, NotFoundException } from "@nestjs/common"; import { map, take } from "rxjs"; import { EsResponseDto, SearchQueryDto} from "../../domain/dtos"; import { EsQueryDto } from "../../domain/dtos/elastic/es-query.dto"; /** * Search service provider */ @Injectable() export class SearchService { /** * Constructs the service with injection of * HTTPService instance * @param httpService */ constructor(private readonly httpService: HttpService) {} /** * Elastichsearch server port-number */ private readonly ES_PORT = process.env.ES_PORT; /** * Elasticsearch IP address */ private readonly ES_IP = process.env.ES_CONTAINER_NAME; /** * Finds a paper by its own ID * @param uuid String, that represents unique identifier of a paper * @returns Elasticsearch hits or an error object */ async findByID(uuid: string): Promise { // Should I change 'object' to specific DTO? const es_query: EsQueryDto = new EsQueryDto(); es_query.size = 1; es_query.query = { query_string: { query: ('id:' + uuid), } } return new Promise((resolve, reject) => { try { (this.httpService.get(`http://${this.ES_IP}:${this.ES_PORT}/_search`, { data: es_query, headers: {'Content-Type': 'application/json'}, })) ?.pipe(take(1), map(axiosRes => axiosRes.data)) .subscribe((res: EsResponseDto) => { if (res.timed_out) { reject(new GatewayTimeoutException('Elasticsearch Timed Out')); } if (!res?.hits?.hits?.length) { reject(new NotFoundException); } resolve(res); }); } catch (error) { reject(error); } }); } /** * Finds relevant documents by context using the given query string * @param query, * @returns Elasticsearch response */ async findByContext(query: SearchQueryDto): Promise { // Contruct a body for querying Elasticsearch const es_query: EsQueryDto = new EsQueryDto(); es_query.query = { query_string: { query: query.query, default_field: 'content', } }; es_query.from = query.offset; es_query.size = query.limit; return new Promise((resolve, reject) => { try { (this.httpService.get(`http://${this.ES_IP}:${this.ES_PORT}/_search`, { data: es_query, headers: {'Content-Type': 'application/json'}, })) ?.pipe(take(1), map(axiosRes => axiosRes.data)) ?.subscribe((res: EsResponseDto) => { if (res.timed_out) { reject(new GatewayTimeoutException('Elasticsearch Timed Out')); } resolve(res); }); } catch (error) { reject(error); } }); } }