TypeORM supports the Adjacency list and Closure table patterns for storing tree structures. To learn more about the hierarchy table take a look at this awesome presentation by Bill Karwin.
Adjacency list is a simple model with self-referencing. The benefit of this approach is simplicity, a drawback is that you can't load big trees all at once because of join limitations. To learn more about the benefits and use of Adjacency Lists look at this article by Matthew Schinckel. Example:
Nested set is another pattern of storing tree structures in the database. It is very efficient for reads, but bad for writes. You cannot have multiple roots in the nested set. Example:
You can specify the closure table name and/or closure table column names by setting optional parameter options into @Tree("closure-table", options). ancestorColumnName and descandantColumnName are callback functions, which receive the primary column's metadata and return the column's name.
There are other special methods to work with tree entities through TreeRepository:
findTrees - Returns all trees in the database with all their children, children of children, etc.
consttreeCategories=awaitdataSource.manager.getTreeRepository(Category).findTrees()// returns root categories with sub categories insideconsttreeCategoriesWithLimitedDepth=awaitdataSource.manager.getTreeRepository(Category).findTrees({ depth:2 })// returns root categories with sub categories inside, up to depth 2
findRoots - Roots are entities that have no ancestors. Finds them all. Does not load children's leaves.
constrootCategories=awaitdataSource.manager.getTreeRepository(Category).findRoots()// returns root categories without sub categories inside
findDescendants - Gets all children (descendants) of the given entity. Returns them all in a flat array.
constchildren=awaitdataSource.manager.getTreeRepository(Category).findDescendants(parentCategory)// returns all direct subcategories (without its nested categories) of a parentCategory
findDescendantsTree - Gets all children (descendants) of the given entity. Returns them in a tree - nested into each other.
constchildrenTree=awaitrepository.findDescendantsTree(parentCategory)// returns all direct subcategories (with its nested categories) of a parentCategoryconstchildrenTreeWithLimitedDepth=awaitrepository.findDescendantsTree( parentCategory, { depth:2 },)// returns all direct subcategories (with its nested categories) of a parentCategory, up to depth 2
createDescendantsQueryBuilder - Creates a query builder used to get descendants of the entities in a tree.
findAncestors - Gets all parents (ancestors) of the given entity. Returns them all in a flat array.
constparents=awaitrepository.findAncestors(childCategory)// returns all direct childCategory's parent categories (without "parent of parents")
findAncestorsTree - Gets all parents (ancestors) of the given entity. Returns them in a tree - nested into each other.
constparentsTree=awaitdataSource.manager.getTreeRepository(Category).findAncestorsTree(childCategory)// returns all direct childCategory's parent categories (with "parent of parents")
createAncestorsQueryBuilder - Creates a query builder used to get the ancestors of the entities in a tree.
relations - Indicates what relations of entity should be loaded (simplified left join form).
Examples:
consttreeCategoriesWithRelations=awaitdataSource.manager.getTreeRepository(Category).findTrees({ relations: ["sites"],})// automatically joins the sites relationconstparentsWithRelations=awaitdataSource.manager.getTreeRepository(Category).findAncestors(childCategory, { relations: ["members"],})// returns all direct childCategory's parent categories (without "parent of parents") and joins the 'members' relation