Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

283
Vistas
Unable to make tree with closure-table in typeorm

I'm currently working on a project where I need a tree in my database. To me, closure-table is the best bet because I will, at some point need multiple roots in the graph.

I am using typeorm 0.2.45 since nestJs doesn't support 0.3.* yet.

When adding entities to the database, without linkage, no problem:

// ./entity/Node.ts
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, Tree, PrimaryColumn, TreeParent, TreeChildren } from "typeorm"

@Entity()
@Tree("closure-table")
export class Node extends BaseEntity {

    @PrimaryColumn()
    name: string

    @TreeParent()
    parent: Node

    @TreeChildren()
    children: Node[]

}
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"

AppDataSource.connect().then(async (conn) => {
    const rNode = conn.getTreeRepository(Node)

    await rNode.createQueryBuilder().delete().execute()

    const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
        await rNode.insert({name})
        return rNode.findOne(name)
    }))

    console.log(await rNode.findTrees())
}).catch(error => console.log(error))

yields

[
  Node { name: 'root', children: [] },
  Node { name: 'child', children: [] }
]

But as soon as I try to add relations within the tree, all goes bad..

import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"

AppDataSource.connect().then(async (conn) => {
    const rNode = conn.getTreeRepository(Node)

    await rNode.createQueryBuilder().delete().execute()

    const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
        await rNode.insert({name})
        return rNode.findOne(name)
    }))

    child.parent = root;
    await rNode.save(child);

    console.log(await rNode.findTrees())
}).catch(error => console.log(error))

Yields

[ Node { name: 'root', children: [] } ]

And the table node_closure is completely empty (note that when filling it properly I do have the tree appearing).

What have I done wrong ?

Thanks

about 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Found the answer, in fact it seems that using repository.insert does not properly updates the closure table (supposed to contain identity relation).

Since identity does not exist, it cannot be propagated when changing parent.

Corrected code is

import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"

AppDataSource.connect().then(async (conn) => {
    const rNode = conn.getTreeRepository(Node)

    await rNode.createQueryBuilder().delete().execute()

    const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
        await rNode.save({name})
        return rNode.findOne(name)
    }))

    child.parent = root;
    await rNode.save(child);

    console.log(await rNode.findTrees())
}).catch(error => console.log(error))

Be careful though, since save is an equivalent of upsert and can and will update an entity if an entity with same primary key is found.

about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda