TypeORM查询结果中如何便捷排除密码等指定字段?
在TypeORM中默认排除实体的password字段
问题描述
我定义了如下TypeORM实体:
export class Users extends BaseEntity { @PrimaryGeneratedColumn() id: bigint @Column({ type: 'varchar', length: 32 }) username: string @Column({ type: 'varchar', length: 32 }) password: string }
执行const data = await Users.find({})查询时,结果会包含password字段,我希望默认从查询结果中排除该字段。
我知道可以通过select选项指定字段:
const data = await Users.find({ select: { username: true, password: false } })
但实际场景中用户表有26+列,不想逐个列写在select配置里,想找更简便的方案,比如在实体定义中直接设置字段默认排除(类似Mongoose的password: { select: false }),或者用预取中间件实现。
解决方案
1. 实体字段配置默认不选择
TypeORM的@Column装饰器支持select参数,设置为false后,该字段默认不会被查询返回,和Mongoose的写法逻辑一致:
@Column({ type: 'varchar', length: 32, select: false }) password: string
此时执行Users.find({})默认不会包含password字段。如果需要在特定场景获取password,可手动在查询中指定包含:
// 单条查询手动选中password const user = await Users.findOne({ where: { id: 1 }, select: ['id', 'username', 'password'] }) // 或用查询构建器 const user = await Users.createQueryBuilder('user') .select(['user.id', 'user.username', 'user.password']) .where('user.id = :id', { id: 1 }) .getOne()
2. 利用查询构建器自动排除字段
若不想修改实体配置,可通过实体元数据获取所有字段,过滤掉password后再查询,避免手动罗列所有字段:
import { getRepository } from "typeorm"; const userRepo = getRepository(Users); // 获取实体所有字段名 const allFields = userRepo.metadata.columns.map(col => col.propertyName); // 排除password字段 const selectFields = allFields.filter(field => field !== 'password'); const users = await userRepo.find({ select: selectFields });
也可以用查询构建器的removeSelect方法直接移除指定字段:
const users = await Users.createQueryBuilder('user') .select() // 默认选中所有字段 .removeSelect('user.password') .getMany()
3. 重写实体的toJSON方法
在实体类中重写toJSON方法,序列化时自动剔除password字段,适合需要返回JSON格式数据的场景:
export class Users extends BaseEntity { @PrimaryGeneratedColumn() id: bigint @Column({ type: 'varchar', length: 32 }) username: string @Column({ type: 'varchar', length: 32 }) password: string toJSON() { const { password, ...rest } = this; return rest; } }
注意:实体对象本身仍会包含password字段,仅在转为JSON时被移除。
4. 使用TypeORM订阅者自动处理
通过订阅者监听实体加载事件,在数据返回前自动移除password字段:
import { EventSubscriber, EntitySubscriberInterface, LoadEvent } from "typeorm"; import { Users } from "./users.entity"; @EventSubscriber() export class UserSubscriber implements EntitySubscriberInterface<Users> { listenTo() { return Users; } afterLoad(event: LoadEvent<Users>) { delete event.entity.password; } }
需要在TypeORM配置的subscribers数组中注册该订阅者,之后所有Users实体的查询结果都会自动剔除password字段。
内容的提问来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

