【问题标题】:Can I get postgres to automatically generate ids for pairs of objects using typeorm?我可以让 postgres 使用 typeorm 为成对的对象自动生成 id 吗?
【发布时间】:2020-10-25 07:14:42
【问题描述】:

背景

我们的节点应用程序使用 postgres 数据库并通过 TypeORM 与其交互。

我知道如何使用由 postgres 序列生成的主键作为 described here 创建一个表:

import {Entity, PrimaryGeneratedColumn} from "typeorm";

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;
}

目标

我正在尝试为总是成对创建的对象创建一个表;让我们将对象称为“鞋子”,并假设这对的两个成员是左鞋和右鞋。我希望左鞋和右鞋在我的表中是单独的条目,并且我希望能够轻松地查询成双中的两双鞋。

一种方法是这样的,它会在pairId 上为我提供一个索引,并为每双强制执行一只左鞋和一只右鞋 (TypeORM index docs)

enum Foot {
    Left = "Left",
    Right = "Right"
}

@Entity()
@Index(["foot", "pairId"], { unique: true })
export class Shoe {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ type: "enum", enum: Foot })
    foot: Foot;

    @Column
    pairId: number
}

但是,这种方法我仍然负责在pairId 字段中生成值。

问题

有没有办法让 postgres 为我生成 pairId 中的值?也许使用@PrimaryGeneratedColumn 装饰器自动生成的同一种序列?

更新

Response below 在 postgres 中提出了一个可能的解决方案,尽管我仍然需要知道如何通过使用 TypeORM 的 API 或让 TypeORM 在正确的时间运行相关的原始 SQL 命令来做到这一点。

我可以编写一个 TypeORM migration 来运行原始 SQL,但我不确定如何让它在创建表时运行——似乎文档主要预期从命令行运行它们。

【问题讨论】:

    标签: node.js postgresql typeorm


    【解决方案1】:

    是的,您可以在 Postgres 中为列分配序列。首次使用:

    https://www.postgresql.org/docs/12/sql-createsequence.html

    CREATE SEQUENCE my_seq OWNED BY shoes.pair_id

    OWNED BY 是可选的,但会将序列“绑定”到表中,因此它会自动与表一起删除。

    然后您可以将序列设为列的默认值:

    test(5432)=# create table shoes (pair_id integer DEFAULT nextval('my_seq'));
    CREATE TABLE
    test(5432)=# \d shoes 
                              Table "public.shoes"
     Column  |  Type   | Collation | Nullable |           Default           
    ---------+---------+-----------+----------+-----------------------------
     pair_id | integer |           |          | nextval('my_seq'::regclass)
    
    

    或者对于现有的表:

    test(5432)=# create table shoes (pair_id integer);
    CREATE TABLE
    
    test(5432)=# alter table shoes alter COLUMN pair_id SET DEFAULT nextval('my_seq');
    ALTER TABLE
    

    我不知道你会如何在 TypeORM 中做到这一点。

    【讨论】:

    • 谢谢!这让我们至少走到了一半:-) 希望一些 TypeORM 专家知道如何在 TypeORM 中执行此操作(或者至少让 TypeORM 在正确的时间执行这些 SQL 命令。
    【解决方案2】:

    我没有 TypeORM 最模糊的想法,但直接 SQL 只是创建一个带有复合键、生成的 id 和左/右值的表。然后,您可以通过单个语句插入两者。

    create table shoes (pair_id integer generated by default as identity
                        ,foot    text
                        ,constraint shoes_pk
                                    primary key (pair_id, foot)
                        ,constraint foot_check 
                                    check (lower (foot) = any('{left, right}') )
                        );                                          
     
    with this_pair(id) as
       ( insert into shoes(foot) 
         values ('left')
         returning pair_id 
       )
    insert into shoes(pair_id,foot)
      select id,'right'
        from this_pair
    returning pair_id ; 
     
    select * from shoes;   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 2010-11-26
      • 2011-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多