NextJS中MongoDB模型在API路由报错,前端调用正常求排查
从前端调用操作MongoDB模型的Server Action完全正常,但通过API路由调用同一个Server Action时出现错误,错误信息如下:
database/question.model.ts (49:0) @
Cannot read properties of undefined (reading 'Question')
报错对应代码行:const Question = models.Question || model("Question", QuestionSchema);
相关代码
1. MongoDB模型代码
import { Schema, models, model, Document } from "mongoose"; export interface IQuestion extends Document { quetions: string; author: Schema.Types.ObjectId[]; answers: string; } const QuestionSchema = new Schema({ questions: { type: String, required: true }, author: { type: Schema.Types.ObjectId, ref: "User" }, answers: { type: String, required: false }, }); const Question = models.Question || model("Question", QuestionSchema); export default Question;
2. Server Action代码
export async function getQuestionsCount(params: GetCountByAuthorParams) { try { connectToDatabase(); const { author } = params; console.log("Author", author); const query: FilterQuery<typeof Question> = { author, }; const totalQuestions = await Question.countDocuments(query); return totalQuestions; } catch (error) { console.log(error); throw error; } }
3. 前端调用(正常工作)
const params = { author: userIdRef.current!, }; const total = await getQuestionsCount(params); console.log("Total Count", total);
4. API路由调用(无法工作)
const params: GetCountByAuthorParams = { author: authorID!, }; const total = await getQuestionsCount(params); console.log("Total Count", total);
问题原因与解决方案
核心原因
问题出在数据库连接的时序上:你在Server Action里调用connectToDatabase()时没有用await等待连接完成,就直接去访问Mongoose的models对象了。
前端调用Server Action时,Next.js的执行机制可能隐性处理了连接等待的逻辑;但API路由是独立的请求处理流程,没有这个隐性处理,导致模型加载时models对象还未被Mongoose初始化,所以会报Cannot read properties of undefined (reading 'Question')。
修复步骤
修改Server Action,等待数据库连接完成
在connectToDatabase()前添加await,确保连接成功后再操作模型:export async function getQuestionsCount(params: GetCountByAuthorParams) { try { // 关键:添加await等待连接完成 await connectToDatabase(); const { author } = params; console.log("Author", author); const query: FilterQuery<typeof Question> = { author }; const totalQuestions = await Question.countDocuments(query); return totalQuestions; } catch (error) { console.log(error); throw error; } }确保数据库连接函数是单例模式
检查你的connectToDatabase()实现,要避免重复创建连接,比如可以这样写:import mongoose from "mongoose"; let isConnected = false; export async function connectToDatabase() { if (isConnected) { return; } try { await mongoose.connect(process.env.MONGODB_URI!); isConnected = true; console.log("数据库连接成功"); } catch (error) { console.error("数据库连接失败:", error); throw error; } }额外修正:模型接口字段拼写错误
你的IQuestion接口里的quetions是拼写错误,应该改成questions,和Schema中的字段保持一致,避免后续数据操作出现问题:export interface IQuestion extends Document { questions: string; // 修正拼写 author: Schema.Types.ObjectId[]; answers: string; }
内容的提问来源于stack exchange,提问作者Powerup California

