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

Next.js中MongoDB数据库初始化失败问题求助

解决Next.js中MongoDB连接跨页面调用getDb失败的问题

我在Next.js里尝试连接MongoDB,在应用初始化阶段设置了数据库,但在另一个页面调用getDb时失败了。相关代码和报错信息如下:

相关代码

mongo.ts

import { MongoClient, Db, ServerApiVersion } from "mongodb";

let isConnected: boolean = false;
const uri: string = process.env.MONGODB_URI as string;

const client = new MongoClient(uri, {
  serverApi: {
    version: ServerApiVersion.v1,
    strict: true,
    deprecationErrors: true,
  },
});

let db: Db | null = null;

async function connect(): Promise<void> {
  if (!isConnected) {
    await client.connect();
    db = client.db(process.env.MONGO_INITDB_DATABASE);
    isConnected = true;
    console.log(
      "Connected successfully to MongoDB server",
      getDb().databaseName,
    );
  }
}

function getDb(): Db {
  if (!db) {
    throw new Error(
      "Database not initialized. Did you forget to call connect first?",
    );
  }
  return db;
}

async function close(): Promise<void> {
  await client.close();
}

export { connect, getDb, close };

index.tsx

import { connect } from "@/config/mongo";
...

export async function getServerSideProps(context: any) {
  try {
    await connect();
    return { props: {} };
  } catch (error: any) {
    return { props: { error: error.message } };
  }
}

apply.tsx

import { getDb } from "@/config/mongo";
...
export async function getServerSideProps(context: NextPageContext) {
  console.log(
    "Inside getServerSideProps of apply.tsx and database connected is ",
    getDb(),
  );
}

报错信息

error - config/mongo.ts (35:10) @ getDb
error - Error: Database not initialized. Did you forget to call connect first?
    at getDb (webpack-internal:///./config/mongo.ts:35:15)

问题原因

Next.js的getServerSideProps是每个请求独立执行的,不同页面的请求不会共享内存中的变量。你在index.tsx的getServerSideProps里调用了connect,但这个操作只在访问index页面的请求中初始化了db变量;当访问apply页面时,这是一个全新的请求,内存里的db和isConnected会被重置,所以直接调用getDb会报错。

解决方法

方法1:每个页面的getServerSideProps先调用connect

直接修改apply.tsx的逻辑,确保在调用getDb前先执行连接:

import { getDb, connect } from "@/config/mongo";
...
export async function getServerSideProps(context: NextPageContext) {
  await connect(); // 先完成数据库连接
  console.log(
    "Inside getServerSideProps of apply.tsx and database connected is ",
    getDb(),
  );
  return { props: {} }; // 必须返回props,否则Next.js会抛出错误
}

方法2:优化连接复用(推荐)

Next.js生产环境会复用服务器进程,我们可以利用这一点优化连接逻辑,避免重复创建连接,同时兼容开发环境的热重载:

import { MongoClient, Db, ServerApiVersion } from "mongodb";

const uri: string = process.env.MONGODB_URI as string;
const dbName: string = process.env.MONGO_INITDB_DATABASE as string;

// 全局变量存储实例,避免开发环境热重载重复创建连接
declare global {
  var mongoClient: MongoClient | undefined;
  var mongoDb: Db | undefined;
}

let client: MongoClient;
let db: Db;

if (process.env.NODE_ENV === "development") {
  if (!global.mongoClient) {
    global.mongoClient = new MongoClient(uri, {
      serverApi: {
        version: ServerApiVersion.v1,
        strict: true,
        deprecationErrors: true,
      },
    });
  }
  client = global.mongoClient;
  if (!global.mongoDb) {
    global.mongoDb = client.db(dbName);
  }
  db = global.mongoDb;
} else {
  // 生产环境直接创建实例,进程复用会保留连接
  client = new MongoClient(uri, {
    serverApi: {
      version: ServerApiVersion.v1,
      strict: true,
      deprecationErrors: true,
    },
  });
  db = client.db(dbName);
}

async function connect(): Promise<void> {
  // 检查连接状态,避免重复连接
  if (!client.topology || !client.topology.isConnected()) {
    await client.connect();
    console.log("Connected successfully to MongoDB server", db.databaseName);
  }
}

function getDb(): Db {
  if (!db) {
    throw new Error("Database not initialized. Did you forget to call connect first?");
  }
  return db;
}

async function close(): Promise<void> {
  await client.close();
}

export { connect, getDb, close };

修改后,每个页面的getServerSideProps仍需先调用connect确保连接状态:

// apply.tsx
export async function getServerSideProps(context: NextPageContext) {
  await connect();
  const dbInstance = getDb();
  // 在这里执行数据库操作
  return { props: {} };
}

关键注意点

  • 不要假设不同请求会共享内存变量,每个请求在开发环境可能是全新实例,生产环境是进程复用,但仍需保证连接状态正确。
  • 永远在调用getDb前执行connect,确保数据库连接已建立。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:13:13