TypeORM设置select:false无法排除主键列,如何解决?
问题
我知道可以给列添加select: false选项来排除其被查询,但要排除的两列是实体的主键,设置后并未生效,主键仍会被包含。推测TypeORM因为主键用于实体标识或外键关联,所以无法直接通过该选项排除。
示例代码如下:
import { Entity, Column, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; import { Timestamps } from "../../shared/entities/timestamps.entity"; import { User } from "../../users/entities/users.entity"; import { Project } from './project.entity'; @Entity('project_invites') export class ProjectInvite extends Timestamps { // Joined Column @PrimaryColumn({select: false}) // <= 不生效 invitedUserId: string; // Joined Column @PrimaryColumn({select: false}) // <= 不生效 projectId: string; @Column({select: false}) fromUserId: string; @Column({nullable: true}) message: string; @ManyToOne(() => User, { onDelete: 'SET NULL' }) @JoinColumn({ name: 'invitedUserId' }) invitedUser: User; @ManyToOne(() => Project, (project) => project.members, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'projectId' }) project: Project; @ManyToOne(() => User, (user) => user.projectInvites, { onDelete: 'SET NULL' }) @JoinColumn({ name: 'fromUserId' }) fromUser: User; }
我使用invitedUserId、fromUserId、projectId列来插入带关联的实体,但查询数据时只想返回关联的实体对象。请问除了手动从结果中移除这些属性外,还有其他TypeORM原生的解决方法吗?
解决方案
以下是几个TypeORM原生的解决方法,无需手动删除结果中的属性:
- 使用查询构建器精准控制返回字段
通过createQueryBuilder显式指定需要的字段和关联,完全跳过主键ID列:
const invites = await getRepository(ProjectInvite) .createQueryBuilder("invite") .select(["invite.message", "invitedUser", "project", "fromUser"]) .leftJoin("invite.invitedUser", "invitedUser") .leftJoin("invite.project", "project") .leftJoin("invite.fromUser", "fromUser") .getMany();
这种方式能完全掌控返回内容,不会包含任何未指定的字段。
- 创建视图实体
如果需要频繁获取这类无主键ID的结果,可以定义视图实体,基于原实体构造只包含所需内容的结构:
@ViewEntity({ expression: (connection) => connection.createQueryBuilder() .select("invite.message", "message") .addSelect("invitedUser.*", "invitedUser") .addSelect("project.*", "project") .addSelect("fromUser.*", "fromUser") .from(ProjectInvite, "invite") .leftJoin("invite.invitedUser", "invitedUser") .leftJoin("invite.project", "project") .leftJoin("invite.fromUser", "fromUser") }) export class ProjectInviteView { @ViewColumn() message: string; @ViewColumn() invitedUser: User; @ViewColumn() project: Project; @ViewColumn() fromUser: User; }
后续查询该视图实体即可直接得到目标结构。
- 在查询时用
select参数覆盖默认配置
在find或findOne方法中,通过select参数指定要包含的非关联字段,关联实体通过relations加载,最终结果不会包含主键ID:
const invites = await getRepository(ProjectInvite).find({ select: ["message"], relations: ["invitedUser", "project", "fromUser"] });
内容的提问来源于stack exchange,提问作者beckersense
相关产品推荐
相关产品推荐

