如何在 DTO 中定义 ObjectId 以及在 NestJS Mongoose 中获取关系数据的正确查询是啥?

Posted

技术标签:

【中文标题】如何在 DTO 中定义 ObjectId 以及在 NestJS Mongoose 中获取关系数据的正确查询是啥?【英文标题】:How to define ObjectId in DTO & what is the right query to get relational data in NestJS Mongoose?如何在 DTO 中定义 ObjectId 以及在 NestJS Mongoose 中获取关系数据的正确查询是什么? 【发布时间】:2021-02-21 04:37:58 【问题描述】:

我正在使用 NestJS、Angular、GraphQL 和 MongoDB 设置应用程序,并且是这些堆栈的新手 我有 2 个名为 TasksStatuses 的集合,其中包含示例数据

任务

[
  "_id": 
    "$oid": "5f9138f71163a739c43fc9b3"
  ,
  "TaskDesc": "Meeting with Brian",
  "StartedDate": "2020-10-22T07:42:40Z",
  "EndDate": "2020-10-22T10:42:40Z",
  "StatusId": "5f91375d1163a739c43fc9af"
]

状态

[
  "_id": 
    "$oid": "5f91375d1163a739c43fc9af"
  ,
  "StatusDesc": "Done"
]

这里是 NestJS 中定义的模式

import  Schema, Types  from 'mongoose';
import  MongooseModule  from '@nestjs/mongoose';

export const TaskSchema = new Schema(
    TaskDesc: String,
    StartedDate: String,
    EndDate: String,
    StatusId:  
    
        type: Types.ObjectId, 
        ref: 'Statuses'
    
);

export const StatusSchema = new Schema(
    StatusDesc: String
);

export const SchemaGroups = MongooseModule.forFeature([
    name: 'Tasks', schema: TaskSchema, collection: 'Tasks',
    name: 'Statuses', schema: StatusSchema, collection: 'Statuses'
]);

DTO

import  ObjectType, Field, ID  from '@nestjs/graphql';

@ObjectType()
export class TasksDTO 
  @Field(() => ID)
  id?: string;
  @Field()
  TaskDesc: string;
  @Field()
  StartedDate: string;
  @Field()
  EndDate: string;
  @Field()
  StatusId: string;


@ObjectType()
export class StatusDTO 
  @Field(() => ID)
  readonly id?: string;
  @Field()
  readonly StatusDesc: string;


型号

import  Document, Schema  from 'mongoose';
export interface Tasks extends Document 
    readonly TaskDesc : string,
    readonly StartedDate: string,
    readonly EndDate: string,
    readonly StatusId: Schema.Types.ObjectId

export interface Status extends Document 
    readonly StatusDesc : string

解析器

@Resolver('Tasks')
export class ListTodoResolver 
    constructor(private readonly todoItemsService: TodolistService)

    

    @Query(() => [TasksDTO])
    async Tasks(): Promise<TasksDTO[]> 
      return await this.todoItemsService.getAllTasks();
    

    @Query(() => [StatusDTO])
    async Statuses(): Promise<StatusDTO[]>
      return await this.todoItemsService.getAllStatuses();
    

服务

import  Injectable  from '@nestjs/common';
import  InjectModel  from '@nestjs/mongoose';
import  Model  from 'mongoose';
@Injectable()
export class TodolistService 
    constructor(
        @InjectModel('Tasks') private readonly todoItemsModel: Model<Tasks>,
        @InjectModel('Statuses') private readonly statusItemsModel: Model<Status>
    )  

    async getAllTasks() : Promise<Tasks[]>
        let tasks = await this.todoItemsModel.find().exec(); // how should we query in the service to get relational data from another collection?
        console.log(tasks);
         
        return tasks;
    

    async getAllStatuses() : Promise<Status[]>
        return await this.statusItemsModel.find().exec();
    

我有这些错误 Type 'Tasks' is not assignable to type 'TasksDTO'. Types of property 'StatusId' are incompatible. Type 'ObjectId' is not assignable to type 'string'.

我们如何在 DTO 中定义 ObjectId 类型? 我对getAllTasks() 方法的预期输出是

[
  "_id": "5f9138f71163a739c43fc9b3",
  "TaskDesc": "Meeting with Brian",
  "StartedDate": "2020-10-22T07:42:40Z",
  "EndDate": "2020-10-22T10:42:40Z",
  "StatusDesc": "Done"
]

【问题讨论】:

【参考方案1】:

错误已经显示在哪里应该修复它。

类型“Tasks”不可分配给类型“TasksDTO”。属性“StatusId”的类型不兼容。类型“ObjectId”不可分配给类型“字符串”。

这意味着你的 DTO 应该是

@ObjectType()
export class TasksDTO 
  @Field(() => ID)
  id?: string;
  @Field()
  TaskDesc: string;
  @Field()
  StartedDate: string;
  @Field()
  EndDate: string;
  @Field()
  StatusId: objectId; // change here

不确定 DTO 中的对象 ID 类型,尝试在文档中查找 DTO 是否有对象 ID 类型,如果没有,则应将所有位置的 StatusId 更改为字符串,这样应该可以工作

【讨论】:

以上是关于如何在 DTO 中定义 ObjectId 以及在 NestJS Mongoose 中获取关系数据的正确查询是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 NestJs 框架中使用 postgres 和 sequelize 正确定义 DTO 对象

如何将自定义 ObjectId 添加到解析服务器对象?

从产品展示页面谈谈Hybris系列之二: DTO, Converter和Populator

java项目中VO和DTO以及Entity,各自是在啥情况下应用的

使用AutoMapper实现Dto和Model的自由转换(下)

DTO中的继承和自定义逻辑[关闭]