| 514 | |
| 515 | const queryTypesDescendantMap = types.length ? models.generateDescendantMap(types) : models.getAllDescendantMap(); |
| 516 | async function findDescendants(docs: BaseModel[]): Promise<BaseModel[]> { |
| 517 | let foundDocs: BaseModel[] = []; |
| 518 | |
| 519 | if (docs.length > 0) { |
| 520 | // Find all descendants of the current docs |
| 521 | const promises: Promise<BaseModel[]>[] = []; |
| 522 | |
| 523 | const uniqueDescendantTypes = new Set<AllTypes>(); |
| 524 | const parentIdsMap = new Map<AllTypes, (string | null)[]>(); |
| 525 | |
| 526 | for (const d of docs) { |
| 527 | if (d.type) { |
| 528 | queryTypesDescendantMap[d.type]?.forEach(t => { |
| 529 | uniqueDescendantTypes.add(t); |
| 530 | parentIdsMap.set(t, [...(parentIdsMap.get(t) || []), d._id]); |
| 531 | }); |
| 532 | } |
| 533 | } |
| 534 | |
| 535 | const queryTypes = Array.from(uniqueDescendantTypes); |
| 536 | |
| 537 | for (const type of queryTypes) { |
| 538 | // If the doc is null, we want to search for parentId === null |
| 539 | const promise = database.find(type, { parentId: { $in: parentIdsMap.get(type) || [] } }); |
| 540 | promises.push(promise); |
| 541 | } |
| 542 | |
| 543 | const docBatches = await Promise.all(promises); |
| 544 | foundDocs = [...foundDocs, ...docBatches.flat()]; |
| 545 | } |
| 546 | |
| 547 | if (foundDocs.length === 0) { |
| 548 | // Didn't find anything. We're done |
| 549 | return docsToReturn; |
| 550 | } |
| 551 | |
| 552 | // Continue searching for children |
| 553 | docsToReturn = [...docsToReturn, ...foundDocs]; |
| 554 | return findDescendants(foundDocs); |
| 555 | } |
| 556 | |
| 557 | return findDescendants([doc]); |
| 558 | }, |