in src/elasticSearchService.ts [140:252]
async typeSearch(request: TypeSearchRequest): Promise<SearchResponse> {
this.assertValidTenancyMode(request.tenantId);
const { queryParams, resourceType } = request;
try {
const from = queryParams[SEARCH_PAGINATION_PARAMS.PAGES_OFFSET]
? Number(queryParams[SEARCH_PAGINATION_PARAMS.PAGES_OFFSET])
: 0;
const size = queryParams[SEARCH_PAGINATION_PARAMS.COUNT]
? Number(queryParams[SEARCH_PAGINATION_PARAMS.COUNT])
: DEFAULT_SEARCH_RESULTS_PER_PAGE;
if (from + size > MAX_ES_WINDOW_SIZE) {
logger.info(
`Search request is out of bound. Trying to access ${from} to ${
from + size
} which is outside of the max: ${MAX_ES_WINDOW_SIZE}`,
);
throw new InvalidSearchParameterError(
`Search parameters: ${SEARCH_PAGINATION_PARAMS.PAGES_OFFSET} and ${SEARCH_PAGINATION_PARAMS.COUNT} are accessing items outside the max range (${MAX_ES_WINDOW_SIZE}). Please narrow your search to access the remaining items`,
);
}
const filter = this.getFilters(request);
const parsedChainParameters = parseChainedParameters(
this.fhirSearchParametersRegistry,
request.resourceType,
request.queryParams,
);
let chainedParameterQuery;
if (parsedChainParameters.length > 0) {
chainedParameterQuery = await this.getChainedParametersQuery(parsedChainParameters, request, filter);
if (isEmpty(chainedParameterQuery)) {
// chained parameter query did not return any results
return {
result: {
numberOfResults: 0,
entries: [],
message: '',
},
};
}
}
const query = buildQueryForAllSearchParameters(
this.fhirSearchParametersRegistry,
request,
this.useKeywordSubFields,
filter,
chainedParameterQuery,
);
const params: Query = {
resourceType,
queryRequest: {
from,
size,
track_total_hits: true,
body: {
query,
},
},
};
if (request.queryParams[SORT_PARAMETER]) {
params.queryRequest.body!.sort = buildSortClause(
this.fhirSearchParametersRegistry,
resourceType,
request.queryParams[SORT_PARAMETER],
);
}
const { total, hits } = await this.executeQuery(params, request);
const result: SearchResult = {
numberOfResults: total,
entries: this.hitsToSearchEntries({ hits, baseUrl: request.baseUrl, mode: 'match' }),
message: '',
};
if (from !== 0) {
result.previousResultUrl = this.createURL(
request.baseUrl,
{
...queryParams,
[SEARCH_PAGINATION_PARAMS.PAGES_OFFSET]: from - size,
[SEARCH_PAGINATION_PARAMS.COUNT]: size,
},
resourceType,
);
}
if (from + size < total) {
result.nextResultUrl = this.createURL(
request.baseUrl,
{
...queryParams,
[SEARCH_PAGINATION_PARAMS.PAGES_OFFSET]: from + size,
[SEARCH_PAGINATION_PARAMS.COUNT]: size,
},
resourceType,
);
}
const includedResources = await this.processSearchInclusions(result.entries, request);
result.entries.push(...includedResources);
const iterativelyIncludedResources = await this.processIterativeSearchInclusions(result.entries, request);
result.entries.push(...iterativelyIncludedResources);
return { result };
} catch (error) {
logger.error(error);
throw error;
}
}