You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:45:35