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

Next.js 14.2中MongoDB findOneAndUpdate无法正常工作的问题

解决Next.js 14.2中MongoDB更新comment字段的错误

问题背景

使用Next.js 14.2修改MongoDB的comment字段时,遇到两个核心错误:

  • 调用connectDB()时,报错:Error connecting to MongoDB: TypeError: Cannot read properties of undefined (reading '0')
  • 不调用connectDB()时,报错:TypeError: _mongodb_proposalSchema__WEBPACK_IMPORTED_MODULE_2__.default.findOneAndUpdate is not a function

另外,相同代码复制到单独目录用npx ts-node index.ts运行完全正常。

相关代码

服务端操作函数(addAComment)

export async function addAComment(proposalId: number, newComment: string) {
  const updateFields: any = {};
  updateFields.comment = newComment;
  console.log("here is a new comment:", newComment);
  const result = await ProposalModel.findOneAndUpdate(
    { proposalId: proposalId },
    { $set: updateFields },
    { new: true }
  );

  console.log("comment added, this is resut:", result);
}

connectDB代码

import mongoose from "mongoose";

const connectDB = async () => {
  try {
    if (mongoose.connections[0].readyState) {
      console.log("Already connected to MongoDB");
      return;
    }

    await mongoose.connect(process.env.MONGODB_URI as string, {
      //serverSelectionTimeoutMS: 70000,
    });

    console.log("Connected to MongoDB");
  } catch (error) {
    console.error("Error connecting to MongoDB:", error);
    throw error;
  }
};

export default connectDB;

前端处理逻辑

const [comment, setComment] = useState("");
const handleSendTransaction = async () => {
  if (comment.length) {
    await addAComment(proposalId, comment);
  }
};
....
<button onClick={handleSendTransaction}>
  Send Transaction
</button>

Schema定义

import { Document, Model, Schema, model, models } from "mongoose";

interface IProposalDocument extends Document {
  proposalId: number;
  toCompanyAddress: string;
  fromAddress: string;
  proposalURI: string;
  decisionStatus: number;
  fundingGoal: string;
  currentFunding: string;
  deadline: string;
  comment?: string;
}

const proposalSchema: Schema<IProposalDocument> = new Schema(
  {
    proposalId: {
      type: Number,
      required: true,
      unique: true,
    },
    toCompanyAddress: {
      type: String,
      required: true,
    },
    fromAddress: {
      type: String,
      required: true,
    },
    proposalURI: {
      type: String,
      required: true,
    },
    decisionStatus: {
      type: Number,
      required: true,
    },
    fundingGoal: {
      type: String,
      required: true,
    },
    currentFunding: {
      type: String,
      required: true,
    },
    deadline: {
      type: String,
      required: true,
    },
    comment: {
      type: String,
      default: "",
    },
  },
  { timestamps: true }
);

const ProposalModel: Model<IProposalDocument> =
  models?.proposals || model<IProposalDocument>("proposals", proposalSchema);

解决方案

1. 修复connectDB的连接状态判断逻辑

原代码直接访问mongoose.connections[0],当连接未初始化时connections为空数组,导致读取[0]报错。修改为更可靠的判断方式:

const connectDB = async () => {
  try {
    // 直接检查当前连接的就绪状态
    const isConnected = mongoose.connection.readyState === 1;
    if (isConnected) {
      console.log("Already connected to MongoDB");
      return;
    }

    await mongoose.connect(process.env.MONGODB_URI as string);
    console.log("Connected to MongoDB");
  } catch (error) {
    console.error("Error connecting to MongoDB:", error);
    throw error;
  }
};

2. 把数据库操作移到API路由(核心修复)

Next.js客户端组件无法直接运行mongoose代码,必须通过API路由或Server Component处理数据库请求。

步骤1:创建API路由文件app/api/add-comment/route.ts

import connectDB from "@/lib/mongodb/connectDB";
import ProposalModel from "@/lib/mongodb/proposalSchema";
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  try {
    await connectDB();
    const { proposalId, newComment } = await request.json();
    
    const result = await ProposalModel.findOneAndUpdate(
      { proposalId },
      { $set: { comment: newComment } },
      { new: true }
    );

    if (!result) {
      return NextResponse.json({ error: "Proposal not found" }, { status: 404 });
    }

    return NextResponse.json({ success: true, data: result });
  } catch (error) {
    return NextResponse.json({ error: (error as Error).message }, { status: 500 });
  }
}

步骤2:修改前端调用逻辑

const [comment, setComment] = useState("");
const handleSendTransaction = async () => {
  if (!comment.length) return;

  try {
    const res = await fetch("/api/add-comment", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ proposalId, newComment: comment }),
    });

    if (!res.ok) throw new Error("Failed to add comment");
    const data = await res.json();
    console.log("Comment added:", data);
  } catch (err) {
    console.error("Error adding comment:", err);
  }
};

3. 确保Model正确导出

检查Schema文件末尾是否正确导出ProposalModel:

// 在proposalSchema.ts末尾添加
export default ProposalModel;

关键原因说明

  • Next.js客户端环境无法运行mongoose,必须通过服务端环境(API路由/Server Component)处理数据库操作。
  • 原connectDB的连接状态判断逻辑存在漏洞,当无连接时mongoose.connections为空数组,直接读取[0]会触发undefined错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:01:12