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

NestJS+TypeORM一对一关系数据保存:避免用户文档存Token详情

解决TypeORM MongoDB关联时仅存储关联ID而非嵌入实体的问题

在MongoDB环境下,TypeORM的OneToOne关联默认会将关联实体完整嵌入到主文档中,这就是你看到User文档里包含Token详情的原因。要实现仅存储关联ID的引用式关联,需要显式配置外键列并调整关联装饰器的参数。

修改后的实体代码

UserEntity

@Entity('Users')
export class UserEntity {
  @ObjectIdColumn()
  _id: ObjectId;

  @Column({ type: 'string', length: 24 })
  name: string;

  @Column({ type: 'string', length: 55 })
  password: string;

  @Column({ type: 'string', length: 24 })
  email: string;

  @Column({ type: 'number' }) // number类型不支持length配置,已移除无效属性
  celphone: number;

  // 新增:单独存储Token的关联ID
  @Column({ type: 'objectid', nullable: true })
  tokenId: ObjectId;

  // 调整关联配置:指定外键列,关闭自动嵌入,保留级联创建逻辑
  @OneToOne(() => TokenEntity, token => token.user, {
    cascade: true,
    eager: false, // 避免查询User时自动加载Token,按需手动加载
  })
  @JoinColumn({ name: 'tokenId' }) // 关联到上面定义的tokenId字段
  token: TokenEntity;

  @CreateDateColumn()
  created_at: Date;

  @UpdateDateColumn()
  updated_at: Date;
}

TokenEntity

@Entity('UserTokens')
export class TokenEntity {
  @ObjectIdColumn()
  _id: ObjectId;

  // 新增:单独存储User的关联ID
  @Column({ type: 'objectid', nullable: true })
  userId: ObjectId;

  // 调整关联配置,指定外键列
  @OneToOne(() => UserEntity, user => user.token)
  @JoinColumn({ name: 'userId' })
  user: UserEntity;

  @Column({ type: 'string', length: 100 })
  accessToken: string;

  @Column({ type: 'number' })
  expireIn: number; // 修正拼写错误:expereIn → expireIn
}

仓库代码无需修改

你原有的CreateUserRepo逻辑保持不变即可。当你设置createUser.token = createUserByToken并执行save时,TypeORM会自动将Token的_id存入User的tokenId字段,而不是嵌入整个Token对象,同时依然会级联创建Token数据到UserTokens集合中。

额外注意事项

  • 如果需要在查询User时同时获取Token数据,可以在查询时添加relations: ['token']参数手动加载关联数据。
  • 确保数据库中已存在的旧数据可以通过迁移脚本更新,新增tokenId和userId字段并填充对应关联ID。

内容的提问来源于stack exchange,提问作者Christian Guimarães

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:40:30