Skip to content

Commit

Permalink
docs(core): Update docs for joinTreeRelationsDynamically
Browse files Browse the repository at this point in the history
  • Loading branch information
monrostar committed Mar 20, 2024
1 parent 8a15a26 commit d6c50d5
Showing 1 changed file with 21 additions and 34 deletions.
55 changes: 21 additions & 34 deletions packages/core/src/service/helpers/utils/tree-relations-qb-joiner.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
/**
* Verifies if a relation has already been joined in a query builder to prevent duplicate joins.
* This method ensures query efficiency and correctness by maintaining unique joins within the query builder.
*
* @param {SelectQueryBuilder<T>} qb The query builder instance where the joins are being added.
* @param {string} alias The join alias to check for uniqueness. This alias is used to determine if the relation
* has already been joined to avoid adding duplicate join statements.
* @returns boolean Returns true if the relation has already been joined (based on the alias), false otherwise.
* @template T extends VendureEntity The entity type for which the query builder is configured.
*/
import { EntityMetadata, SelectQueryBuilder } from 'typeorm';
import { EntityTarget } from 'typeorm/common/EntityTarget';

Expand Down Expand Up @@ -37,33 +27,30 @@ function isTreeEntityMetadata(metadata: EntityMetadata): boolean {
}

/**
* These method are designed to address specific challenges encountered with TypeORM
* when dealing with complex relation structures, particularly around the 'collection'
* entity and other similar entities, and they nested relations ('parent', 'children'). The need for these custom
* implementations arises from limitations in handling deeply nested relations and ensuring
* efficient query generation without duplicate joins, as discussed in TypeORM issue #9936.
* See https://github.com/typeorm/typeorm/issues/9936 for more context.
* Dynamically joins tree relations and their eager counterparts in a TypeORM SelectQueryBuilder, addressing
* challenges of managing deeply nested relations and optimizing query efficiency. It leverages TypeORM tree
* decorators (@TreeParent, @TreeChildren) to automate joins of self-related entities, including those marked for eager loading.
* The process avoids duplicate joins and manual join specifications by using relation metadata.
*
* @param {SelectQueryBuilder<T>} qb - The query builder instance for joining relations.
* @param {EntityTarget<T>} entity - The target entity class or schema name, used to access entity metadata.
* @param {string[]} [requestedRelations=[]] - An array of relation paths (e.g., 'parent.children') to join dynamically.
* @param {number} [maxEagerDepth=1] - Limits the depth of eager relation joins to avoid excessively deep joins.
* @returns {Map<string, string>} - A Map of joined relation paths to their aliases, aiding in tracking and preventing duplicates.
* @template T - The entity type, extending VendureEntity for compatibility with Vendure's data layer.
*
* Dynamically joins tree relations and their eager relations to a query builder. This method is specifically
* designed for entities utilizing TypeORM tree decorators (@TreeParent, @TreeChildren) and aims to address
* the challenge of efficiently managing deeply nested relations and avoiding duplicate joins. The method
* automatically handles the joining of related entities marked with tree relation decorators and eagerly
* loaded relations, ensuring efficient data retrieval and query generation.
* Usage Notes:
* - Only entities utilizing TypeORM tree decorators and having nested relations are supported.
* - The `maxEagerDepth` parameter controls the recursion depth for eager relations, preventing performance issues.
*
* The method iterates over the requested relations paths, joining each relation dynamically. For tree relations,
* it also recursively joins all associated eager relations. This approach avoids the manual specification of joins
* and leverages TypeORM's relation metadata to automate the process.
* For more context on the issue this function addresses, refer to TypeORM issue #9936:
* https://github.com/typeorm/typeorm/issues/9936
*
* @param {SelectQueryBuilder<T>} qb The query builder instance to which the relations will be joined.
* @param {EntityTarget<T>} entity The target entity class or schema name. This parameter is used to access
* the entity's metadata and analyze its relations.
* @param {string[]} requestedRelations An array of strings representing the relation paths to be dynamically joined.
* Each string in the array should denote a path to a relation (e.g., 'parent.parent.children').
* @param maxEagerDepth The maximum depth of eager relations to join. This parameter is used to limit the depth of eager relations.
* @returns {Map<string, string>} A Map containing the paths of relations that were dynamically joined with their aliases. This map can be used
* to track which relations have been processed and potentially avoid duplicate processing.
* @template T extends VendureEntity The type of the entity for which relations are being joined. This type parameter
* should extend VendureEntity to ensure compatibility with Vendure's data access layer.
* Example:
* ```typescript
* const qb = repository.createQueryBuilder("entity");
* joinTreeRelationsDynamically(qb, EntityClass, ["parent.children"], 2);
* ```
*/
export function joinTreeRelationsDynamically<T extends VendureEntity>(
qb: SelectQueryBuilder<T>,
Expand Down

0 comments on commit d6c50d5

Please sign in to comment.