You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js13中Mongoose报MissingSchemaError:未注册post模型

解决Mongoose "Schema hasn't been registered for model 'post'" 错误

错误原因

  1. 连接上下文不兼容:当前使用原生MongoClient连接数据库,但Mongoose需要依赖自身的连接机制管理模型与Schema,两者上下文不互通,导致Mongoose无法识别已注册的模型。
  2. 模型注册逻辑错误:mongoose.model("post") || mongoose.model("post", PostSchema)的写法存在问题——第一次调用mongoose.model("post")时模型尚未注册,会直接抛出MissingSchemaError,无法执行后续的模型创建逻辑。

解决方案

1. 替换数据库连接方式为Mongoose原生连接

修改mongodb.ts文件内容,使用Mongoose官方的连接逻辑:

import mongoose from "mongoose";

if (!process.env.MONGODB_URI) {
  throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
}

const uri = process.env.MONGODB_URI;
let isConnected = false;

async function connectDB() {
  if (isConnected) return;

  try {
    await mongoose.connect(uri);
    isConnected = true;
    console.log("MongoDB connected via Mongoose");
  } catch (error) {
    throw new Error(`Failed to connect to MongoDB: ${error}`);
  }
}

export default connectDB;

2. 修正Post模型的注册逻辑

修改Post.ts(建议将文件名从Post.tsx改为Post.ts,因为这是数据模型而非React组件):

import mongoose from "mongoose";
import Joi from "joi";

type Post = {
  name: string;
  prompt: string;
  photo: string;
};

const PostSchema = new mongoose.Schema({
  name: { type: String, required: true },
  prompt: { type: String, required: true },
  photo: { type: String, required: true },
});

// 处理开发环境HMR导致的模型重复注册问题
const Post = mongoose.models.Post || mongoose.model<Post>("Post", PostSchema);

function validatePost(data: Post) {
  const schema = Joi.object({
    name: Joi.string().min(1).max(100).required(),
    prompt: Joi.string().min(2).required(),
    photo: Joi.string().required(),
  });
  return schema.validate(data);
}

export { validatePost };
export default Post;

说明:

  • 使用mongoose.models.Post检查模型是否已存在,避免开发环境热重载时重复注册模型。
  • 模型名采用首字母大写的Post,Mongoose会自动映射到数据库的posts集合(符合MongoDB命名规范)。

3. 更新API文件,确保先完成Mongoose连接

修改API文件中的连接逻辑,必须等待Mongoose连接完成后再操作模型:

import type { NextApiRequest, NextApiResponse } from "next";
import connectDB from "@/lib/mongodb/mongodb";
import { v2 as cloudinary } from "cloudinary";
import Post from "@/lib/mongodb/models/post";
import { validatePost } from "@/lib/mongodb/models/post";

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

export const config = {
  api: {
    bodyParser: {
      sizeLimit: "50mb",
    },
    responseLimit: false,
  },
};

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // 先等待Mongoose连接完成
  await connectDB();

  if (req.method === "GET") {
    try {
      const posts = await Post.find({});
      res.status(200).json({ success: true, data: posts });
    } catch (err) {
      res.status(500).json({
        success: false,
        message: "Fetching posts failed, please try again",
      });
    }
  } else if (req.method === "POST") {
    try {
      const { error } = validatePost(req.body);
      if (error) return res.status(400).send(error.details[0].message);
      const { name, prompt, photo } = req.body;
      const photoUrl = await cloudinary.uploader.upload(photo);
      const post = new Post({
        name,
        prompt,
        photo: photoUrl.url,
      });
      const newPost = await post.save();
      res.status(200).json({ success: true, data: newPost });
    } catch (err) {
      res.status(500).json({
        success: false,
        message: "Unable to create a post, please try again",
      });
    }
  } else {
    res.status(405).json({ success: false, message: "Method not allowed" });
  }
}

额外注意事项

  • 确保MONGODB_URI环境变量格式正确,Mongoose支持与原生MongoClient相同的连接字符串格式。
  • 开发环境中Next.js的热重载(HMR)可能导致模型重复注册,因此必须保留mongoose.models.Post的检查逻辑。

内容的提问来源于stack exchange,提问作者Jahanzaib Tayyab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:45:53