97 lines
3.3 KiB
TypeScript
97 lines
3.3 KiB
TypeScript
import { HttpService } from "@nestjs/axios";
|
|
import { GatewayTimeoutException, ImATeapotException, Injectable, NotFoundException } from "@nestjs/common";
|
|
import { map, take } from "rxjs";
|
|
import { EsMultimatchQueryDto } from "src/core/domain/dtos/elastic/es-multimatch.dto";
|
|
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<EsResponseDto> { // 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<EsResponseDto>(`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, <EsQueryDto>
|
|
* @returns Elasticsearch response
|
|
*/
|
|
async findByContext(query: SearchQueryDto): Promise<EsResponseDto> {
|
|
// Contruct a body for querying Elasticsearch
|
|
const es_query: EsMultimatchQueryDto = new EsMultimatchQueryDto(query.query, [
|
|
'title', 'content'
|
|
]);
|
|
es_query.from = query.offset;
|
|
es_query.size = query.limit;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
(this.httpService.get<EsResponseDto>(`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);
|
|
}
|
|
});
|
|
}
|
|
} |