无法在 typeorm 中使用 closure-table 创建树

Unable to make tree with closure-table in typeorm

我目前正在做一个项目,我的数据库中需要一棵树。对我来说,closure-table 是最好的选择,因为我会在某些时候需要图中的多个根。

我正在使用 typeorm 0.2.45,因为 nestJs 还不支持 0.3.*。

向数据库中添加实体时,没有链接,没有问题:

// ./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))

产量

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

但是当我尝试在树中添加关系时,一切都变糟了..

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))

产量

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

并且 table node_closure 完全是空的(请注意,当正确填充它时,我确实会出现树)。

我做错了什么?

谢谢

找到了答案,实际上似乎使用repository.insert没有正确更新闭包table(应该包含恒等关系)。

由于身份不存在,因此无法在更改父级时传播它。

更正后的代码是

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))

不过要小心,因为保存等同于更新插入,如果找到具有相同主键的实体,则可以并且将会更新实体。