【Nestjs学习日记】Schema 的 Ref

作者:markzzw 时间:2024-2-26

线上代码:CodeSandbox

Github:zhangzewei/nest-learning-tutorial
系列阅读 【Nestjs学习日记】专栏

在 mongoDB 的 Schema 中,可以将字段定义为另一个数据表中的数据的 ObjectId,很多情况会用到,例如:cat 表中的 foods 应该为另一个 foods 表中的数据,这样就不用每次都填入字符串,而是在 foods 表中的数据挑选,也方便在 UI 界面中进行多选的操作。

新建 Food Module

1. food.module.ts

ts 复制代码
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { Food, FoodSchema } from './food.schema';
import { FoodController } from './food.controller';
import { FoodService } from './food.service';

@Module({
    imports: [
        MongooseModule.forFeature([{
            name: Food.name,
            schema: FoodSchema
        }])
    ],
    controllers: [FoodController],
    providers: [FoodService],
    exports: [FoodService]
})
export class FoodModule { }

2. food.schema.ts

ts 复制代码
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type FoodDocument = HydratedDocument<Food>;

@Schema()
export class Food {
    @Prop()
    name: string;

    @Prop()
    brand: string;
}
export const FoodSchema = SchemaFactory.createForClass(Food);

3. food.servicets

ts 复制代码
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { CreateFoodDto } from './food.dto';
import { Food } from './food.schema';
@Injectable()
export class FoodService {
    isChanged = false;
    constructor(
        @InjectModel(Food.name) private foodModel: Model<Food>
    ) { }

    async findAll() {
        return this.foodModel.find();
    }

    async create(createFoodDto: CreateFoodDto) {
        const createdCat = new this.foodModel(createFoodDto);
        return createdCat.save();
    }
}

4. food.controller.ts

ts 复制代码
import { Controller, Get, Body, Post, Param, Put } from '@nestjs/common';
import { CreateFoodDto } from './food.dto';
import { FoodService } from './food.service';

@Controller('food')
export class FoodController {
    constructor(
        private foodService: FoodService
    ) { }
    @Get()
    findAll() {
        return this.foodService.findAll();
    }

    @Post()
    createCat(@Body() body: CreateFoodDto) {
        return this.foodService.create(body);
    }
}

5. food.dto.ts

ts 复制代码
import { IsString, IsNumber, IsArray } from 'class-validator';
import { PartialType } from '@nestjs/mapped-types';

export class CreateFoodDto {
  @IsString()
  name: string;
  @IsString()
  brand: string;
}

export class UpdateFoodDto extends PartialType(CreateFoodDto) { }

录入food数据

修改 cat scheme 的 foods 的描述

可以看到这里的类型为引用,引用的值为 foods 表中的 objectId,所以接下来调用 postman 的 cat post 请求,其中 foods 的值为 food 的 _id。

数据库中的 cats 的foods数据是 objectId

验证

修改 cat service 中的 findAll 函数。

ts 复制代码
async findAll() {
    const cats = await this.catModel.find();
    const foods = await this.foodService.findAll();
    cats.map(cat => {
      const newFoods = cat.foods.map(fid =>
          foods.find(fd => 
              fd.id.toString() === fid.toString()
          )
      );
      cat.foods = newFoods;
      return cat;
    });
    return cats;
 }

这样就能够通过food id获取到对应的food的详细数据。

相关推荐
木斯佳2 分钟前
前端八股文面经大全:腾讯前端暑期提前批一、二、三面面经(下)(2026-03-04)·面经深度解析
前端
bluceli11 分钟前
前端国际化(i18n)实战指南:构建多语言应用的完整方案
前端
hh随便起个名21 分钟前
React组件通信
前端·react.js·前端框架
前端 贾公子24 分钟前
vite-plugin-eruda-pro 在vite中使用eruda
前端
Jackson__1 小时前
Agent Skill 和 Rules 有什么区别?
前端·agent·ai编程
不要卷鸿蒙啊1 小时前
【鸿蒙开发】HMRouter一款和好用的管理路由三方工具
前端·harmonyos
李剑一1 小时前
数字孪生大屏必看:Cesium 3D 模型选中交互,3 种高亮效果拿来就用!
前端·vue.js·cesium
奶昔不会射手1 小时前
自定义vue3函数式弹窗
前端·javascript·css
new code Boy2 小时前
前端全栈之路
前端
牛奶2 小时前
为什么敲几个字母就能访问网站?DNS原理大揭秘
前端·http·dns