NestJS TypeORM如何拥有ManyToOne关系成员,哪种类型是conditional



我有一个实体Message,它有sender(User(和receiver,但receiver可以是UserChannel(两个实体都有messagesIn成员(,我想使用TypeORM关系来实现这一点。

有可能用TypeORM(postgres(/NestJS做这样的事情吗(或者有其他传统的方法来实现同样的目标吗(?

// message.entity.ts
@Entity()
export class Message {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
content: string;
@ManyToOne(() => User, (snd) => snd.messagesOut)
sender: User;
// That line doesn't compile
@ManyToOne(() => User | Channel, (rcv) => rcv.messagesIn)
receiver: User | Channel;
};

您试图做的事情是不可能的,因为TypeORM需要确切地知道您试图填充的实体,这样它才能在正确的位置进行查询。

TypeORM有一些机制,允许您创建一个表,所有来自User和Channel的记录都将插入其中,请参阅此处的更多信息。

但是,如果您希望每个实体都有两个专用表(也称为"每类型继承表"(,我建议创建另一个名为Receiver的实体,该实体包含UserChannel之间与消息传递机制相关的公共属性,以及一个称为type的属性,该属性将定义接收方是User还是Channel;然后在两个表中的每一个表中引用CCD_ 14实体。

export enum ReceiverType {
USER = 'USER',
CHANNEL = 'CHANNEL',
}
@Entity()
export class Receiver {
@PrimaryGeneratedColumn('uuid')
id: string;
// all common properties that you want related to messaging goes here
@OneToMany(() => Message, (msg) => msg.receiver)
messagesIn: Message[];
@Column({
type: "enum",
enum: ReceiverType,
})
type: ReceiverType
}
@Entity()
export class User {
// user properties...
@OneToOne(() => Receiver)
@JoinColumn()
receiver: Receiver
}
@Entity()
export class Channel {
// channel properties...
@OneToOne(() => Receiver)
@JoinColumn()
receiver: Receiver
}

然后,在Message实体中,您将能够引用Receiver:

@Entity()
export class Message {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
content: string;
@ManyToOne(() => User, (snd) => snd.messagesOut)
sender: User;
@ManyToOne(() => Receiver, (rcv) => rcv.messagesIn)
receiver: Receiver;
};

因此,当您通过存储库获得消息实体时,您将收到类似以下内容:

{
id: string;
content: string;
sender: { ... };
receiver: {
// common properties you defined...
messagesIn: [ ... ],
type: ReceiverType,
}
}

有了这些信息,您将能够访问您想要的、消息发送流所需的数据,并且,如果您需要一些仅存在于UserChannel实体中的特定信息,您可以从Receiver获取type,并通过接收方id检索相应的实体,例如:

if (message.receiver.type === ReceiverType.USER) {
const user = await userRepository.findOne({
where: {
receiver: { id: message.receiver.id },
},
});
...
}
if (message.receiver.type === ReceiverType.CHANNEL) {
const user = await channelRepository.findOne({
where: {
receiver: { id: message.receiver.id },
},
});
...
}

不能有一列是多个表中的外键;FK必须始终引用单个表中的特定列/列集。通过定义引用每个表的可为null的列来处理这种情况,然后放置一个要求其中一个为null的约束。不幸的是,我对您的模糊化管理器(TypeORM(不够熟悉,所以我还将提供一个原始的Postgres表定义。

Create table Message( id          uuid default gen_random_uuid()
primary key
, content     text 
, sender_user uuid
references users(id) 
, rcv_user    uuid 
references users(id) 
, rcv_channel uuid 
references channels(id)                   
, constraint  only_user_or_channel_ck 
check ( num_nulls(rcv_user,rcv_channel) = 1 )
); 

当然,这会对表、它们的键和列类型进行假设。

最新更新