in src/elasticSearchService.ts [458:504]
private async processIterativeSearchInclusions(
searchEntries: SearchEntry[],
request: TypeSearchRequest,
): Promise<SearchEntry[]> {
if (!ITERATIVE_INCLUSION_PARAMETERS.some((param) => request.queryParams[param])) {
return [];
}
const result: SearchEntry[] = [];
const resourceIdsAlreadyInResult: Set<string> = new Set(
searchEntries.map((searchEntry) => searchEntry.resource.id),
);
const resourceIdsWithInclusionsAlreadyResolved: Set<string> = new Set();
logger.info('Iterative inclusion search starts');
let resourcesToIterate = searchEntries;
for (let i = 0; i < MAX_INCLUDE_ITERATIVE_DEPTH; i += 1) {
// eslint-disable-next-line no-await-in-loop
const resourcesFound = await this.processSearchInclusions(resourcesToIterate, request, true);
resourcesToIterate.forEach((resource) =>
resourceIdsWithInclusionsAlreadyResolved.add(resource.resource.id),
);
if (resourcesFound.length === 0) {
logger.info(`Iteration ${i} found zero results. Stopping`);
break;
}
resourcesFound.forEach((resourceFound) => {
// Avoid duplicates in result. In some cases different include/revinclude clauses can end up finding the same resource.
if (!resourceIdsAlreadyInResult.has(resourceFound.resource.id)) {
resourceIdsAlreadyInResult.add(resourceFound.resource.id);
result.push(resourceFound);
}
});
if (i === MAX_INCLUDE_ITERATIVE_DEPTH - 1) {
logger.info('MAX_INCLUDE_ITERATIVE_DEPTH reached. Stopping');
break;
}
resourcesToIterate = resourcesFound.filter(
(r) => !resourceIdsWithInclusionsAlreadyResolved.has(r.resource.id),
);
logger.info(`Iteration ${i} found ${resourcesFound.length} resources`);
}
return result;
}