我有以下模式
export type MapDocument = Map & Document
@Schema({
timestamps: true,
versionKey: false,
id: true
})
export class Map {
constructor(partial?: Partial<Map>) {
if (partial)
Object.assign(this, partial)
}
@IsOptional()
@IsUUID()
@Prop({ type: Object, default: uuidv4, required: false})
@Exclude({ toPlainOnly: true })
_id?: Object
@ApiPropertyOptional({ type: String, format: 'uuid' })
@IsOptional()
@IsUUID()
id?: string
@ApiProperty()
@IsAscii()
@MaxLength(10)
@Prop()
building: string
@ApiProperty()
@IsInt()
@Prop()
@Transform(({ value }) => +value, { toClassOnly: true })
floor: number
@ApiPropertyOptional({ type: Image, format: 'uuid'})
@IsOptional()
@IsUUID()
@Prop({ type: String, ref: 'Image' })
@Transform(({ value }) => new Image(value).id, { toClassOnly: true })
image?: string
@ApiProperty({ type: [Marker] })
@IsArray()
@Type(() => Marker)
@Prop({ type: [MarkerSchema] })
markers?: Marker[]
}
const MapSchema = SchemaFactory.createForClass(Map)
MapSchema.index({ building: 1, floor: 1 }, { unique: true });
const mongooseLeanVirtuals = require('mongoose-lean-virtuals')
MapSchema.plugin(mongooseLeanVirtuals);
export { MapSchema }
export class UpdateMap extends PartialType(Map) {}
标记声明如下
export type MarkerDocument = Marker & Document
@Schema({
timestamps: true,
versionKey: false,
id: true
})
export class Marker {
constructor(partial?: Partial<Marker>) {
if (partial)
Object.assign(this, partial)
}
@IsOptional()
@IsUUID()
@Prop({ type: Object, default: uuidv4, required: false})
@Exclude({ toPlainOnly: true })
_id?: Object
@ApiPropertyOptional({ type: String, format: 'uuid' })
@IsOptional()
@IsUUID()
id?: string
@ApiPropertyOptional({ type: Desk, format: 'uuid'})
@IsOptional()
@IsUUID()
@Prop({ type: String, required: false, ref: 'Desk' })
@Transform(({ value }) => new Desk(value).id, { toClassOnly: true })
desk?: string
@ApiProperty()
@IsNumberString()
@Prop()
xPercent: string
@ApiProperty()
@IsNumberString()
@Prop()
yPercent: string
}
const MarkerSchema = SchemaFactory.createForClass(Marker)
const mongooseLeanVirtuals = require('mongoose-lean-virtuals')
MarkerSchema.plugin(mongooseLeanVirtuals);
export { MarkerSchema }
export class UpdateMarker extends PartialType(Marker) {}
重要的是要注意,有一个字段(desk)引用另一个集合,但我不希望这些项目存储在他们自己的集合中,而是作为'maps'集合的子文档直接
'desk'模式声明如下
export type DeskDocument = Desk & Document
@Schema({
timestamps: true,
versionKey: false,
id: true
})
@ApiExtraModels(Image)
export class Desk {
constructor(partial?: Partial<Desk>) {
if (partial)
Object.assign(this, partial)
}
@IsOptional()
@IsUUID()
@Prop({ type: Object, default: uuidv4, required: false})
@Exclude({ toPlainOnly: true })
_id?: Object
@ApiPropertyOptional({ type: String, format: 'uuid' })
@IsOptional()
@IsUUID()
id?: string
@ApiProperty({ type: Board, format: 'uuid'})
@IsUUID('all')
@Prop({ type: String, required: true, ref: 'Board' })
@Transform(({ value }) => value.id, { toClassOnly: true })
board: string
@ApiProperty({ type: [Number] })
@IsArray()
@Prop({ type: () => [Number], required: true })
relays?: number[]
@ApiProperty()
@IsAscii()
@MaxLength(250)
@Prop()
name: string
@ApiProperty()
@IsAscii()
@MaxLength(250)
@Prop()
description: string
@ApiProperty()
@IsAscii()
@MaxLength(10)
@Prop()
building: string
@ApiProperty()
@IsInt()
@Prop()
@Transform(({ value }) => +value, { toClassOnly: true })
floor: number
@ApiProperty()
@IsAscii()
@MaxLength(10)
@Prop()
code: string
@ApiPropertyOptional({ type: [Image], format: 'uuid'})
@IsOptional()
@IsUUID('all', { each: true })
@Prop({ type: [String], required: false, ref: 'Image' })
@Transform(({ value }) => value.id, { toClassOnly: true })
images?: String[]
}
const DeskSchema = SchemaFactory.createForClass(Desk)
DeskSchema.index({ board: 1, relays: 1 }, { unique: true });
const mongooseLeanVirtuals = require('mongoose-lean-virtuals')
DeskSchema.plugin(mongooseLeanVirtuals)
export { DeskSchema }
export class UpdateDesk extends PartialType(Desk) {}
find方法试图填充下至桌面的所有内容(我不需要填充比这更深的内容)
async findAll(): Promise<Map[]> {
return (await this.mapModel.find().populate({
path: 'image',
model: Image,
transform: (doc: Image) => new Image(doc),
}).populate({
path: 'markers',
model: Marker,
transform: (doc: Marker) => new Marker(doc),
populate: {
path: 'desk',
model: Desk,
transform: (doc: Desk) => new Desk(doc),
options: { lean: true, virtuals: true },
}
}).lean({ virtuals: true }).exec())
.map(map => new Map(map))
}
两个问题
小- 如果我没有指定lean: true作为桌面填充的选项,我将得到完整的mongo文档。对于依赖于'lean'设置的'markers'数组来说,情况并非如此 主要
- :桌面对象被填充,但虚拟'id'字段没有这是我得到的输出:
{
"building": "A",
"floor": 1,
"image": {
"name": "OfficePlan12",
"url": "https://drive.google.com/uc?id=1H2nnIRjR2e7Z7yoVnHxLCTaYs8s5iHrT",
"updatedAt": "2022-06-24T09:03:03.786Z",
"id": "2b31f419-e069-4058-813e-54ce0a941440"
},
"updatedAt": "2022-06-26T10:19:22.650Z",
"markers": [
{
"yPercent": "15.853658536585366",
"xPercent": "18.083462132921174",
"desk": {
"images": [
"b85eefee-eeca-4193-87ae-9329fad8256a",
"692743d0-a860-4451-b313-b21a144ef387"
],
"description": "Work like a boss",
"name": "Management desk",
"createdAt": "2022-02-19T21:12:18.832Z",
"updatedAt": "2022-06-07T14:02:13.556Z",
"building": "A",
"code": "01",
"floor": 1,
"relays": [
"1"
],
"board": "932c3e9b-85bd-42c8-9bc0-a318eea7b036"
},
"updatedAt": "2022-06-26T10:19:22.650Z",
"createdAt": "2022-06-26T10:19:22.650Z",
"id": "a8149e84-2f62-46c3-990f-531eff82f6d5"
}
],
"id": "37dc791f-724b-44e2-baaf-bfc606385996"
}
可以看到'desk'对象没有'id'字段.任何帮助将非常感激,谢谢!
我终于找到了一个解决方法。公平地说,它看起来很糟糕,但它确实奏效了。基本上,我修改了"桌面"文档的变换函数,它是我的"内部"文档"图像"的第一个"外部"文档。函数如下所示:
transform: (doc: Desk) => new Desk((new this.deskModel(doc)).toObject({ virtuals: true })),
options: { lean: true },
populate: {
path: 'images',
model: Image,
transform: (doc: Image) => new Image(doc)
}
基本上,我需要在服务构造函数中注入相应的模型,以便能够使用'options'和'populate'调用'toObject'函数。最后,我需要使用获得的对象来构建'Desk'的新实例,以确保类验证函数正确应用于端点。