【问题标题】:Replace _id to id in NestJs + Typegoose在 NestJs + Typegoose 中将 _id 替换为 id
【发布时间】:2020-07-03 09:47:12
【问题描述】:

我使用 NestJs + Typegoose。如何在 NestJs + Typegoose 中将 _id 替换为 id?我没有找到一个明确的例子。我尝试了一些东西,但没有任何结果。

@modelOptions({
  schemaOptions: {
    collection: 'users',
  },
})
export class UserEntity {
  @prop()
  id?: string;

  @prop({ required: true })
  public email: string;

  @prop({ required: true })
  public password: string;

  @prop({ enum: UserRole, default: UserRole.User, type: String })
  public role: UserRole;

  @prop({ default: null })
  public subscription: string;
}
@Injectable()
export class UsersService {
  constructor(
    @InjectModel(UserEntity) private readonly userModel: ModelType<UserEntity>,
  ) {}

  getOneByEmail(email: string) {
    return from(
      this.userModel
        .findOne({ email })
        .select('-password')
        .lean(),
    );
  }
}

【问题讨论】:

  • 您可以将id声明为类类型的公共属性,并定义与默认工厂_id关联的getter和setter。

标签: nestjs typegoose


【解决方案1】:

我可以说这是潜在的猫鼬行为 您可以使用 'id' 而不是 '_id' 发送 JSON,所有模型上的虚拟属性是一种非常安全且简单的方法 去做吧。

一个例子:

export const NotesSchema = new Schema({
  title: String,
  description: String,
});

NotesSchema.virtual('id')
    .get(function() {
      return this._id.toHexString();
});

或者您可以在执行此操作的模型上创建一个 toClient() 方法。这也是重命名/删除您不想发送给客户端的其他属性的好地方:

NotesSchema.method('toClient', function() {
    var obj = this.toObject();

    //Rename fields
    obj.id = obj._id;
    delete obj._id;

    return obj;
});

【讨论】:

  • 感谢您的回答,但this.userModel .findOne({ email }) .select('-password') .lean() 的结果如何转换为对象?因为不是Document也没有toObject()方法
  • 默认情况下,Mongoose 查询返回一个 Mongoose Document 类的实例。 const leanDoc = await MyModel.findOne().lean();如果我理解你倾向于如果没有帮助就必须给出对象 .toJSON();必须工作
【解决方案2】:

将默认 _id 更新为 id 的另一种方法是覆盖 modelOptions 装饰器中的 toJSON 方法。

@modelOptions({
    schemaOptions: {
        collection: 'Order',
        timestamps: true,
        toJSON: {
            transform: (doc: DocumentType<TicketClass>, ret) => {
                delete ret.__v;
                ret.id = ret._id;
                delete ret._id;
            }
        }
    }
})
@plugin(AutoIncrementSimple, [{ field: 'version' }])
class TicketClass {

    @prop({ required: true })
    public title!: string

    @prop({ required: true })
    public price!: number

    @prop({ default: 1 })
    public version?: number
}


export type TicketDocument = DocumentType<TicketClass>


export const Ticket = getModelForClass(TicketClass);



【讨论】:

    【解决方案3】:

    将 typegoose 与类转换器一起使用:

    import * as mongoose from 'mongoose';
    import { Expose, Exclude, Transform } from 'class-transformer';
    
    @Exclude()
    // re-implement base Document to allow class-transformer to serialize/deserialize its properties
    // This class is needed, otherwise "_id" and "__v" would be excluded from the output
    export class DocumentCT {
      @Expose({ name: '_id' })
      // makes sure that when deserializing from a Mongoose Object, ObjectId is serialized into a string
      @Transform((value: any) => {
        if ('value' in value) {
          return value.value instanceof mongoose.Types.ObjectId ? value.value.toHexString() : value.value.toString();
        }
    
        return 'unknown value';
      })
      public id: string;
    
      @Expose()
      public createdAt: Date;
    
      @Expose()
      public updatedAt: Date;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2016-02-22
      • 2022-09-23
      • 1970-01-01
      • 2023-04-09
      • 2020-11-29
      • 2017-10-09
      • 2021-12-19
      • 1970-01-01
      • 2021-03-01
      相关资源
      最近更新 更多