Next.js中仅用类而非实例时findOneAndUpdate无法工作
问题:Mongoose findOneAndUpdate 提示“不是函数”错误
控制台已确认MongoDB连接成功,但调用使用findOneAndUpdate的updateUser函数时,出现以下错误:
Failed to create/update user: _models_user_model__WEBPACK_IMPORTED_MODULE_1__.default.findOneAndUpdate is not a function TypeError: _models_user_model__WEBPACK_IMPORTED_MODULE_1__.default.findOneAndUpdate is not a function
相关代码
updateUser 函数
import { revalidatePath } from "next/cache"; import User from "../models/user.model"; import { connectToDB } from "../mongoose"; interface Params { userId: string; username: string; name: string; bio: string; image: string; path: string; } export async function updateUser({ userId, username, name, bio, image, path, }: Params): Promise<void> { try { // 建立数据库连接 await connectToDB(); // 更新用户文档 console.log(`Modelo ${User}`) await User.findOneAndUpdate( { id: userId }, { username: username.toLowerCase(), name, bio, image, onboarded: true, }, { upsert: true } ); // 必要时重新验证路径 if (path === "/profile/edit") { revalidatePath(path); } } catch (error: any) { // 记录错误用于调试 console.error(`Failed to create/update user: ${error.message}`); // 可选:重新抛出错误以便在其他地方处理 throw error; } }
用户模型(user.model.ts)
import mongoose from "mongoose"; const userSchema = new mongoose.Schema({ id: { type: String, required: true, }, username: { type: String, unique: true, required: true, }, name: { type: String, required: true, }, image: String, bio: String, threads: [ { type: mongoose.Schema.Types.ObjectId, ref: "Thread", }, ], onboarded: { type: Boolean, default: false, }, communities: [ { type: mongoose.Schema.Types.ObjectId, ref: "Community", }, ], }); const User = mongoose.models?.User || mongoose.model('User', userSchema); export default User;
MongoDB 连接文件(mongoose.ts)
"use server" import mongoose from "mongoose"; let isConnected = false; // 跟踪连接状态的变量 export const connectToDB = async () => { // 设置严格查询模式,防止未知字段查询 if (!process.env.NEXT_PUBLIC_MONGODB_URL) return console.log("Missing MongoDB URL"); // 如果连接已建立,无需创建新连接 if (isConnected) { console.log("MongoDB connection already established"); return; } try { await mongoose.connect(process.env.NEXT_PUBLIC_MONGODB_URL); mongoose.set('strictQuery', false); isConnected = true; // 将连接状态设为已连接 console.log("MongoDB connected"); console.log(mongoose.models); } catch (error) { console.log(error); } };
预期与实际情况
预期流程:
- 成功建立MongoDB连接
- 通过
findOneAndUpdate按ID查找并更新用户文档 - 必要时重新验证路径
- 处理更新中的错误
实际情况:连接正常,但findOneAndUpdate被提示不是函数,无法完成更新操作。
解决方案
1. 修正模型导出逻辑
Next.js服务端环境的模块缓存可能导致模型重复定义或未正确初始化,修改用户模型的导出代码,确保模型只被创建一次:
import mongoose from "mongoose"; const userSchema = new mongoose.Schema({ // 保留原有字段定义 }); // 优先使用已存在的模型,避免重复创建 export default mongoose.models.User || mongoose.model('User', userSchema);
2. 确保连接完成后模型已加载
在connectToDB函数中添加模型存在性检查,避免未加载模型就执行操作:
"use server" import mongoose from "mongoose"; import { userSchema } from "../models/user.model"; // 导入Schema let isConnected = false; export const connectToDB = async () => { if (!process.env.NEXT_PUBLIC_MONGODB_URL) return console.log("Missing MongoDB URL"); if (isConnected) { // 确认User模型已加载 if (!mongoose.models.User) { mongoose.model('User', userSchema); } console.log("MongoDB connection already established"); return; } try { await mongoose.connect(process.env.NEXT_PUBLIC_MONGODB_URL); mongoose.set('strictQuery', false); // 显式创建模型(如果未自动创建) if (!mongoose.models.User) { mongoose.model('User', userSchema); } isConnected = true; console.log("MongoDB connected"); console.log(mongoose.models); } catch (error) { console.log(error); } };
3. 检查查询条件正确性
确认查询条件与模型定义匹配:当前使用{ id: userId },模型中确实定义了自定义id字段,这部分没问题;如果使用的是MongoDB默认的_id,则需要改为{ _id: userId }。
4. 重启开发服务器
Next.js的模块缓存可能保留旧的模型代码,重启服务器可清除缓存,确保最新的模型代码被加载。
内容的提问来源于stack exchange,提问作者Diego Motta
相关产品推荐
相关产品推荐

