资讯动态

10分钟上手 Nest.js + MongoDB:用 TaoToken 统一 Key 打通本地开发链路

发布时间:2026/10/1 6:38:18 来源:尧图企业网站定制
1. 为什么本地 Nest.js MongoDB 联调总卡在“最后一公里”Nest.js 配 MongoDB 这套组合写业务代码其实不复杂真正让人反复折腾的往往是环境链路数据库连不上、模块没注入、请求发出去返回一堆看不懂的报错。尤其是当你想在本地把接口调通、再顺手接一个大模型能力做点智能处理时Key 管理、Base URL 配置、模型 ID 对不上三件事凑一起十分钟能起步的项目能拖成一下午。这篇就聚焦一个目标从零初始化一个 Nest.js 项目接上本地 MongoDB跑通第一个 CRUD 接口然后把本地请求的 Base URL 统一改到 TaoToken用同一套 Key 验证接口返回。适合刚接触 Nest.js、想快速把后端骨架搭起来的人也适合已经在写 Node 服务、想把模型调用收口到统一入口的开发者。核心检索词先摆出来Nest.js 怎么连接 MongoDB、Nest.js Mongoose 配置、Nest.js CRUD 接口教程、TaoToken 统一 Key 本地联调。这几个词基本覆盖了从建项目到验证请求的全过程。我试过把 Mongoose 连接、Schema 定义、Service 注入这几步拆开单独调反而更容易定位问题。所以下面按“先跑通数据库、再补 CRUD、最后换 Base URL 验证”的顺序来每一步都能单独验证结果不会出现改了一堆代码不知道哪出错的情况。TaoToken 在这里的角色是统一入口官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址 https://taotoken.net/api 。你本地服务里所有需要调模型的请求Base URL 指向它Key 用同一个模型 ID 按文档填就不用每个服务单独维护一套凭证。2. 前置准备Node 环境、MongoDB 与 TaoToken Key 获取2.1 本地环境清单先把要装的东西列清楚避免中途缺依赖。Node.js 建议 18 LTS 以上Nest.js 11 对 Node 版本有要求。MongoDB 本地装社区版即可默认端口 27017。包管理器用 npm 或 pnpm 都行下面命令统一用 npm。验证 Node 和 npmnode -v npm -vMongoDB 装好后确认服务在跑Windows 可以在服务列表看 MongoDB ServermacOS 用 brew services listLinux 用 systemctl status mongod。连一下确认mongosh能进交互界面就说明本地数据库没问题。这一步别跳过后面 Mongoose 连不上八成是服务没起。2.2 安装 Nest CLI 并创建项目全局装脚手架npm i -g nestjs/cli创建项目名字随意这里叫 nest-mongo-demonest new nest-mongo-demo它会让你选包管理器选 npm。装完进目录cd nest-mongo-demo npm run start:dev看到 Nest 默认的 Hello World 起来说明骨架没问题。默认跑在 3000 端口。2.3 安装 Mongoose 相关依赖Nest 官方对 Mongoose 有封装装两个包npm install mongoose nestjs/mongoose --save如果后面编译报类型错误补一个类型包npm install types/mongoose --dev2.4 获取 TaoToken Key打开 https://taotoken.net/api-keys 登录后创建一个 API Key复制保存。这个 Key 后面会写进 .env不要硬编码到代码里。模型 ID 在文档 https://taotoken.net/doc 里查选一个你常用的对话或补全模型即可。Base URL 统一用 https://taotoken.net/api 。注意Key 只显示一次复制后存到安全的地方。本地开发用 .env 管理记得把 .env 加进 .gitignore。3. 可复制配置.env、Mongoose 连接与模块注入3.1 创建 .env 并写入连接信息项目根目录建 .env 文件# 本地 MongoDB MONGO_URImongodb://127.0.0.1:27017/nest_demo # TaoToken 统一入口 TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_MODEL_ID你的模型ID # 服务端口 PORT3000装 dotenv 让 Nest 读取npm install nestjs/config --save在 app.module.ts 里注册 ConfigModule并让 Mongoose 从环境变量读连接串import { Module } from nestjs/common; import { ConfigModule, ConfigService } from nestjs/config; import { MongooseModule } from nestjs/mongoose; import { AppController } from ./app.controller; import { AppService } from ./app.service; import { UserModule } from ./server/user/user.module; Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), MongooseModule.forRootAsync({ inject: [ConfigService], useFactory: (config: ConfigService) ({ uri: config.getstring(MONGO_URI), }), }), UserModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}这里用 forRootAsync 而不是直接写死字符串是为了后面换环境不用改代码。连接串里的 nest_demo 是数据库名MongoDB 会自动创建。3.2 生成 user 模块、控制器、服务用脚手架生成省得手写nest g module user server nest g controller user server nest g service user server生成后目录结构是 src/server/user/里面三个文件。模块文件会自动注册到 app.module.ts。3.3 定义 Schema 与模块注入在 src/server/user/ 下建 user.schema.tsimport { Schema } from mongoose; export const userSchema new Schema({ _id: { type: String, required: true }, user_name: { type: String, required: true }, password: { type: String, required: true }, });修改 user.module.ts用 forFeature 注册模型import { Module } from nestjs/common; import { MongooseModule } from nestjs/mongoose; import { UserController } from ./user.controller; import { userSchema } from ./user.schema; import { UserService } from ./user.service; Module({ imports: [ MongooseModule.forFeature([{ name: Users, schema: userSchema }]), ], controllers: [UserController], providers: [UserService], }) export class UserModule {}3.4 定义接口类型与 DTO建 user.interface.tsimport { Document } from mongoose; export interface User extends Document { readonly user_name: string; readonly password: string; }建 user.dto.tsexport class CreateUserDTO { readonly user_name: string; readonly password: string; } export class EditUserDTO { readonly user_name: string; readonly password: string; }3.5 在 Service 中注入 Model 并写 CRUDuser.service.tsimport { Injectable } from nestjs/common; import { InjectModel } from nestjs/mongoose; import { Model } from mongoose; import { CreateUserDTO } from ./user.dto; import { User } from ./user.interface; Injectable() export class UserService { constructor( InjectModel(Users) private readonly userModel: ModelUser, ) {} async findAll(): PromiseUser[] { return await this.userModel.find(); } async findOne(user_name: string): PromiseUser { return await this.userModel.findOne({ user_name }); } async addOne(body: CreateUserDTO): Promisevoid { await this.userModel.create(body); } async updateOne(user_name: string, newPassword: string): Promisevoid { await this.userModel.updateOne({ user_name }, { password: newPassword }); } async deleteOne(user_name: string): Promisevoid { await this.userModel.deleteOne({ user_name }); } }3.6 控制器暴露路由user.controller.tsimport { Body, Controller, Get, Post } from nestjs/common; import { CreateUserDTO } from ./user.dto; import { User } from ./user.interface; import { UserService } from ./user.service; interface UserResponseT unknown { code: number; data?: T; message: string; } Controller(user) export class UserController { constructor(private readonly userService: UserService) {} Get(/users) async findAll(): PromiseUserResponseUser[] { return { code: 200, data: await this.userService.findAll(), message: 查询成功., }; } Post(/find_one) async findOne( Body() userData: { user_name: string }, ): PromiseUserResponse { return { code: 200, data: await this.userService.findOne(userData.user_name), message: 查询成功., }; } Post(/user) async addOne(Body() body: CreateUserDTO): PromiseUserResponse { await this.userService.addOne(body); return { code: 200, message: 添加成功. }; } Post(/upd) async updateOne( Body() userData: { user_name: string; newPassword: string }, ): PromiseUserResponse { await this.userService.updateOne( userData.user_name, userData.newPassword, ); return { code: 200, message: 修改成功. }; } Post(/deluser1) async deleteOne( Body() userData: { user_name: string }, ): PromiseUserResponse { await this.userService.deleteOne(userData.user_name); return { code: 200, message: 删除成功. }; } }到这里数据库链路和 CRUD 就齐了。启动服务npm run start:dev看到 Nest 日志里 Mongoose 连接成功、路由映射出来就说明本地链路通了。4. 验证请求把 Base URL 改到 TaoToken 并确认返回4.1 先验证本地 CRUD 接口用 curl 测添加curl -X POST http://localhost:3000/user/user \ -H Content-Type: application/json \ -d {user_name:tom,password:123456}返回{code:200,message:添加成功.}就对了。再查全部curl http://localhost:3000/user/users能看到 tom 这条记录说明 MongoDB 写入和读取都正常。4.2 在服务里接入 TaoToken 统一入口新建一个 ai 模块用来封装模型调用nest g module ai server nest g service ai serverai.service.ts 里用 fetch 调 TaoToken 的对话接口Base URL 从环境变量读import { Injectable } from nestjs/common; import { ConfigService } from nestjs/config; Injectable() export class AiService { constructor(private readonly config: ConfigService) {} async chat(prompt: string): Promisestring { const baseUrl this.config.getstring(TAOTOKEN_BASE_URL); const apiKey this.config.getstring(TAOTOKEN_API_KEY); const model this.config.getstring(TAOTOKEN_MODEL_ID); const res await fetch(${baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${apiKey}, }, body: JSON.stringify({ model, messages: [{ role: user, content: prompt }], }), }); if (!res.ok) { const text await res.text(); throw new Error(TaoToken 请求失败: ${res.status} ${text}); } const data await res.json(); return data.choices?.[0]?.message?.content ?? ; } }ai.module.ts 注册import { Module } from nestjs/common; import { AiService } from ./ai.service; Module({ providers: [AiService], exports: [AiService], }) export class AiModule {}在 app.module.ts 的 imports 里加上 AiModule。4.3 加一个验证路由在 app.controller.ts 里加一个接口调用 AiServiceimport { Controller, Get, Query } from nestjs/common; import { AppService } from ./app.service; import { AiService } from ./server/ai/ai.service; Controller() export class AppController { constructor( private readonly appService: AppService, private readonly aiService: AiService, ) {} Get() getHello(): string { return this.appService.getHello(); } Get(ai/ping) async ping(Query(q) q: string): Promise{ reply: string } { const reply await this.aiService.chat(q || 你好); return { reply }; } }4.4 发起验证请求重启服务后执行curl http://localhost:3000/ai/ping?q用一句话介绍Nest.js如果返回类似{reply:Nest.js 是一个基于 Node.js 的渐进式框架...}说明 Base URL 已经指向 TaoTokenKey 和模型 ID 都生效了。这一步是整个链路的关键验证点本地服务 → TaoToken 统一入口 → 模型返回。想直接在网页里对比不同模型的返回可以用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 把同样的 prompt 丢进去看输出差异再决定本地用哪个模型 ID。5. 本篇常见错排查401、local proxy failed、reading choices5.1 401 Unauthorized报错长这样TaoToken 请求失败: 401 {error:{message:Invalid API key}}原因通常是 Key 没读到或写错了。检查 .env 里 TAOTOKEN_API_KEY 是否完整有没有多余空格。ConfigModule 要确保 isGlobal: true否则 AiService 里注入 ConfigService 拿不到值。另外确认请求头是Authorization: Bearer sk-xxxBearer 后面有一个空格。5.2 local proxy failed / ECONNREFUSEDError: connect ECONNREFUSED 127.0.0.1:27017这是 MongoDB 没起。先mongosh确认能连不行就重启 MongoDB 服务。如果 Mongo 起了还报这个检查 .env 里 MONGO_URI 的端口和主机名别写成 localhost 又解析到 IPv6 去了用 127.0.0.1 更稳。5.3 reading choices of undefinedTypeError: Cannot read properties of undefined (reading choices)说明返回体里没有 choices 字段。常见原因是模型 ID 填错或者请求路径不对。TaoToken 的对话接口路径是/v1/chat/completionsBase URL 是 https://taotoken.net/api 拼起来就是 https://taotoken.net/api/v1/chat/completions 。如果模型 ID 在文档里查不到对应项换一个确认可用的。另外先打印一下res.status和原始文本别直接 res.json()不然错误信息被吞掉。5.4 OAuth / 鉴权相关报错如果看到 OAuth 或 token 过期类提示先确认用的是 API Key 而不是其他凭证。API Key 在 https://taotoken.net/api-keys 管理过期或删掉的 Key 会直接 401。重新生成一个换进 .env 即可。5.5 Mongoose 模型注入失败Nest cant resolve dependencies of the UserService (?, ...)这是 forFeature 没注册或 name 对不上。检查 user.module.ts 里MongooseModule.forFeature([{ name: Users, schema: userSchema }])的 name 和 Service 里InjectModel(Users)是否一致大小写敏感。6. 把 Key 收口到一处本地开发链路才算真正打通走到这里你手上应该有一个能跑的 Nest.js 服务、一个连上的 MongoDB、一组 CRUD 接口以及一个通过 TaoToken 统一入口调模型的验证路由。整个过程里最值得保留的习惯是把 Base URL、Key、模型 ID 全部放进 .env代码里只读环境变量。这样换模型、换 Key、换环境都不用动业务代码。如果后面要长期写编码类任务或者搭 Agent可以看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 把常用模型和额度规划好。日常调试接口返回控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 能看到请求记录排查 401 或模型不对时比翻日志快。接入文档在 https://taotoken.net/doc 路径和参数以文档为准。最后一个实操建议每次改完 .env 一定要重启 Nest 服务ConfigModule 不会热更新环境变量。这个坑我踩过改了 Key 没重启对着 401 查了半天代码结果只是进程没重载。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑