typescript - TypeORM 更新多对多关系的一部分记录
我在 Channel 和 User 之间有一个多对多的关系,用于向订阅频道的用户发送电子邮件通知。我正在开发一个功能,其中一个频道会被另一个频道取代,但我不知道如何将所有通知从即将解散的频道转移到目标频道。
@Entity()
export class User {
@PrimaryColumn()
id: string
@Column()
createdAt: Date
@Column()
updatedAt: Date
@Column()
email: string
@ManyToMany(_type => Channel)
@JoinTable()
notifications: Channel[]
}
@Entity()
export class Channel {
@PrimaryColumn()
id: string
@Column()
createdAt: Date
@Column()
updatedAt: Date
}
async function transferNotifications(from: unknown, to: unknown): Promise<void> {
//?
}
答案#1
你至少有两个选择:
1. 使用实体管理器
首先,获取所有与 notification 有已解析关系的 User 实体。然后从所有获取到的 User 实体的 notification 属性中删除旧的(已解散的)Channel 实体,如果先前包含旧的实体,再将新的 Channel 实体添加到该数组中。这样会移除对应的关联表行,并在新的频道中添加一行新的记录。
显而易见的缺点是,连接将会在三张表的所有行上执行,所有结果都会加载到应用程序内存中。因此,对于较大的表,这不一定是一个好的解决方案。
2. 使用 QueryBuilder
一个更好的方法是通过添加自定义连接表实体自己构建连接表。然后使用 QueryBuilder 将旧外键替换为新通道的 id。
getRepository(UserChannel).createQueryBuilder()
.update()
.set({ channelId: '<new channel id>' })
.where(`channelId = :channelId`, { channelId: `<old channel id>`})
.execute();
@Entity()
export class User {
@PrimaryColumn()
id: string
@Column()
createdAt: Date
@Column()
updatedAt: Date
@Column()
email: string
@OneToMany(type => UserChannel)
userChannels: UserChannel[]
}
@Entity()
export class UserChannel {
@ManyToOne(type => User)
user!: User;
@Column({ primary: true })
userId!: string;
@ManyToOne(type => Channel)
channel!: channel;
@Column({ primary: true })
channelId!: string;
}
@Entity()
export class Channel {
@PrimaryColumn()
id: string
@Column()
createdAt: Date
@Column()
updatedAt: Date
}
答案#2
如果你在使用 NodeJs,你可以使用 promises 来进行批量更新、删除或其他操作。
你需要做的是将所有更新 map 到数组中,然后使用 Promise.all 解决它们。
新更新。
updates = [{ id: 1, name: "Channel 1" }, { id: 2, name: "Channel 2"}];
批量更新代码
l
let promises = updates.map(update => {
let query = {id: update.id};
delete update.id;
return channelRepository
.update({id update.id}, update)
});
return await Promise.all(promises);
