mongodb NestJS Mongoose模式继承

yhxst69z  于 2022-12-03  发布在  Go
关注(0)|答案(3)|浏览(180)

我尝试在NestJS中继承Mongoose架构或SchemaDefitions,但我没有太多的运气。我这样做是为了共享基本和公共架构定义详细信息,例如虚拟('id')和随机数,我们已经附加到每个实体。每个架构定义在Mongo中都应该有自己的集合,因此鉴别器将不起作用。
我尝试通过以下不同的方式来实现这一点
首先,我定义了以下基本模式定义:

基本架构.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { TimeStamps } from './timestamps.schema';

export type BaseDocument = BaseSchemaDefinition & Document;

@Schema({
  toJSON: {
    virtuals: true,
    transform: function (doc: any, ret: any) {
      delete ret._id;
      delete ret.__v;
      return ret;
    },
  },
})
export class BaseSchemaDefinition {
  @Prop({
    type: Types.ObjectId,
    required: true,
    default: Types.ObjectId,
  })
  nonce: Types.ObjectId;

  @Prop()
  timestamps: TimeStamps;
}

然后,我继承模式定义并创建模式,以便以后可以在我的服务和控制器中使用它,方法如下:

个人.架构.ts

import { Prop, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { BaseSchemaDefinition } from './base.schema';

export type PersonDocument = PersonSchemaDefintion & Document;

export class PersonSchemaDefintion extends BaseSchemaDefinition {
  @Prop({ required: true })
  first_name: string;

  @Prop({ required: true })
  last_name: string;

  @Prop()
  middle_name: string;

  @Prop()
  data_of_birth: Date;

  @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
  addresses: [Address];
}

const PersonSchema = SchemaFactory.createForClass(PersonSchemaDefintion);

PersonSchema.virtual('id').get(function (this: PersonDocument) {
  return this._id;
});

export { PersonSchema };

这导致我只能创建和获取BaseSchemaDefinition中定义的属性。
{“时间戳”:{“已删除”:空,“已更新”:“2021-09- 21 T16:55:17.094Z”,“已创建”:“2021年9月21日16:55:17.094Z”},“_标识”:“随机数”:“614a0e75eb6cb52aa0ccd028”,“__v”:0个字符}
其次,我尝试使用这里描述的方法Inheriting Mongoose schemas(不同的MongoDB集合)实现继承

基本架构.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { TimeStamps } from './timestamps.schema';

export type BaseDocument = BaseSchemaDefinition & Document;

@Schema({
  toJSON: {
    virtuals: true,
    transform: function (doc: any, ret: any) {
      delete ret._id;
      delete ret.__v;
      return ret;
    },
  },
})
export class BaseSchemaDefinition {
  @Prop({
    type: Types.ObjectId,
    required: true,
    default: Types.ObjectId,
  })
  nonce: Types.ObjectId;

  @Prop()
  timestamps: TimeStamps;
}

const BaseSchema = SchemaFactory.createForClass(BaseSchemaDefinition);

BaseSchema.virtual('id').get(function (this: BaseDocument) {
  return this._id;
});

export { BaseSchema };

个人.架构.ts

import { Prop } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { BaseSchema, BaseSchemaDefinition } from './base.schema';

export type PersonDocument = PersonSchemaDefintion & Document;

export class PersonSchemaDefintion extends BaseSchemaDefinition {
  @Prop({ required: true })
  first_name: string;

  @Prop({ required: true })
  last_name: string;

  @Prop()
  middle_name: string;

  @Prop()
  data_of_birth: Date;

  @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
  addresses: [Address];
}

export const PersonSchema = Object.assign(
  {},
  BaseSchema.obj,
  PersonSchemaDefintion,
);

导致相同的输出。不确定为什么继承不执行
以下是使用模式和构建模型的服务代码

人员.服务.ts

import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import {
  PersonSchemaDefintion,
  PersonDocument,
} from 'src/schemas/person.schema';
import { TimeStamps } from 'src/schemas/timestamps.schema';

@Injectable()
export class PersonService {
  constructor(
    @InjectModel(PersonSchemaDefintion.name)
    private personModel: Model<PersonDocument>,
  ) {}

  async create(
    personModel: PersonSchemaDefintion,
  ): Promise<PersonSchemaDefintion> {
    personModel.timestamps = new TimeStamps();
    const createdPerson = new this.personModel(personModel);

    return createdPerson.save();
  }

  async update(
    id: string,
    changes: Partial<PersonSchemaDefintion>,
  ): Promise<PersonSchemaDefintion> {
    const existingPerson = this.personModel
      .findByIdAndUpdate(id, changes)
      .exec()
      .then(() => {
        return this.personModel.findById(id);
      });
    if (!existingPerson) {
      throw Error('Id does not exist');
    }
    return existingPerson;
  }

  async findAll(): Promise<PersonSchemaDefintion[]> {
    return this.personModel.find().exec();
  }

  async findOne(id: string): Promise<PersonSchemaDefintion> {
    return this.personModel.findById(id).exec();
  }

  async delete(id: string): Promise<string> {
    return this.personModel.deleteOne({ _id: id }).then(() => {
      return Promise.resolve(`${id} has been deleted`);
    });
  }
}

如果需要,我可以提供更多详细信息

qqrboqgw

qqrboqgw1#

我想我也有同样问题
这就是我的解决方案:
首先,您需要custom @Schema装饰器。

架构.装饰器.ts

import * as mongoose from 'mongoose';
import { TypeMetadataStorage } from '@nestjs/mongoose/dist/storages/type-metadata.storage';
import * as _ from 'lodash';

export type SchemaOptions = mongoose.SchemaOptions & {
    inheritOption?: boolean
}

function mergeOptions(parentOptions: SchemaOptions, childOptions: SchemaOptions) {
    for (const key in childOptions) {
        if (Object.prototype.hasOwnProperty.call(childOptions, key)) {
            parentOptions[key] = childOptions[key];
        }
    }
    return parentOptions;
}

export function Schema(options?: SchemaOptions): ClassDecorator {
    return (target: Function) => {
        const isInheritOptions = options.inheritOption;

        if (isInheritOptions) {
            let parentOptions = TypeMetadataStorage.getSchemaMetadataByTarget((target as any).__proto__).options;
            parentOptions = _.cloneDeep(parentOptions)  
            options = mergeOptions(parentOptions, options);
        }

        TypeMetadataStorage.addSchemaMetadata({
            target,
            options
        })
    }
}

这是基本架构。

目录.架构.ts

import { Prop, SchemaFactory } from "@nestjs/mongoose";
import { Schema } from '../../common/decorators/schema.decorator'
import { Document } from "mongoose";

export type CatDocument = Cat & Document;

@Schema({
    timestamps: true,
    toJSON: {
        virtuals: true,
        transform: function (doc: any, ret: any) {
            delete ret._id;
            delete ret.__v;
            return ret;
        },
    },
})
export class Cat {
    @Prop()
    name: string;

    @Prop()
    age: number;

    @Prop()
    breed: string;
}

const CatSchema = SchemaFactory.createForClass(Cat);

CatSchema.virtual("id").get(function (this: CatDocument) {
    return this._id;
});

export { CatSchema };

英格兰目录.schema.ts

import { Prop, SchemaFactory } from "@nestjs/mongoose";
import { Schema } from "../../common/decorators/schema.decorator";
import { Document } from "mongoose";
import { Cat } from "../../cats/schemas/cat.schema";

export type EnglandCatDocument = EnglandCat & Document;

@Schema({
    inheritOption: true
})
export class EnglandCat extends Cat {
    @Prop()
    numberLegs: number;
}

export const EnglandCatSchema = SchemaFactory.createForClass(EnglandCat)

EnglandCat是Cat的子类,它继承了Cat的所有选项,如果需要,可以覆盖某些选项。

5vf7fwbs

5vf7fwbs2#

在摆弄了一段时间之后,我发现了在利用这些技术时似乎可以工作的正确组合
下面是基类

基本架构.ts

import { Prop, Schema } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { TimeStamps } from './timestamps.schema';

export type BaseDocument = Base & Document;

@Schema()
export class Base {
  @Prop({
    type: Types.ObjectId,
    required: true,
    default: Types.ObjectId,
  })
  nonce: Types.ObjectId;

  @Prop()
  timestamps: TimeStamps;
}

下面是继承base.schema的类。

个人.架构.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { Address } from './address.schema';
import { Base } from './base.schema';

export type PersonDocument = Person & Document;

@Schema({
  toJSON: {
    virtuals: true,
    transform: function (doc: any, ret: any) {
      delete ret._id;
      delete ret.__v;
      return ret;
    },
  },
})
export class Person extends Base {
  @Prop({ required: true })
  first_name: string;

  @Prop({ required: true })
  last_name: string;

  @Prop()
  middle_name: string;

  @Prop()
  data_of_birth: Date;

  @Prop({ type: [{ type: Types.ObjectId, ref: 'Address' }] })
  addresses: [Address];
}
const PersonSchema = SchemaFactory.createForClass(Person);

PersonSchema.virtual('id').get(function (this: PersonDocument) {
  return this._id;
});

export { PersonSchema };

我唯一想改进的是将虚拟('id ')移到基类中。但是架构继承不起作用。在这一点上,它只对架构定义起作用。这至少让我走上了正确的方向。如果有人有办法改进这一点,请贡献自己的力量。

xkrw2x1b

xkrw2x1b3#

这些Hieu Cao的答案是正确的,因为问题是“模式继承”。您的选中答案与扩展模式无关,它与基本继承类有关,您在Base中没有任何模式选项。

相关问题