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

NodeJS连接MongoDB无法创建集合 createCollection未定义报错

问题描述

8个月前可正常运行的相同代码配置突然失效,访问/createDatabase接口时抛出类型错误,排查发现数据库连接未成功建立,无法定位根因,需要更合理的实现方案。

  • 错误核心表现:全局存储的数据库连接对象con为undefined,调用createCollection方法时触发类型错误
  • 部署方式:基于Docker Compose部署

原有服务端代码

'use strict'

const express = require('express');
const MongoClient = require('mongodb').MongoClient;

const url = 'mongodb://toor:root@mongodbdatabase:27017/'

const app = express();
const PORT = 8080;
const HOST = '0.0.0.0';

let con;
MongoClient.connect(url, (err, db) => {
    con = db.db("mongodbdatabase");
})

app.use('/', express.static('public'));

app.get('/createDatabase', (req, res) => {
    con.createCollection("HiveDB", function(err, result) {
        if (err) throw err;
        console.log("Collection Created")
    })
    res.send();
})

console.log(`Listening on port ${PORT}`)

app.listen(PORT, HOST);

报错信息

TypeError: Cannot read properties of undefined (reading 'createCollection')
    at /usr/src/app/server.js:28:9
    at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
    at next (/usr/src/app/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/usr/src/app/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
    at /usr/src/app/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:346:12)
    at next (/usr/src/app/node_modules/express/lib/router/index.js:280:10)
    at SendStream.error (/usr/src/app/node_modules/serve-static/index.js:121:7)
    at SendStream.emit (node:events:537:28)

原有部署配置

Dockerfile

FROM node:latest

EXPOSE 8080

WORKDIR /usr/src/app

RUN npm install express --save
RUN npm install mongodb --save
RUN npm install -g loadtest --save

COPY server.js /usr/src/app/server.js
COPY /public /usr/src/app/public


CMD ["node", "server.js"]

docker-compose.yml

version: '3'
services:

  mainserver:
    build: ./main
    depends_on:
      - mongodbdatabase
    container_name: mainServer
    ports:
      - "83:8080"


  mongodbdatabase:
    image: mongo
    container_name: monDataBase
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: toor
      MONGO_INITDB_ROOT_PASSWORD: root
问题根因
  • 异步时序错误:MongoClient.connect是异步非阻塞操作,原代码没有等待连接完成就启动了HTTP服务,请求到达接口时连接回调尚未执行,con变量还未赋值,自然是undefined。
  • 无错误处理逻辑:连接回调完全没有捕获连接错误,不管是Mongo未就绪、认证失败还是网络不通,连接失败时没有任何日志输出,直接导致后续数据库实例对象为空。
  • Docker依赖逻辑不生效:depends_on配置仅等待Mongo容器启动完成,不会等待Mongo数据库服务初始化完毕、可接收连接,Node服务启动时大概率Mongo还在初始化,连接直接失败。
  • 版本漂移问题:Dockerfile使用node:latest基础镜像,npm安装依赖也未锁定版本,8个月间MongoDB Node驱动从3.x迭代到4.x+版本,连接默认超时、认证逻辑均有调整,进一步放大了时序问题。
  • 连接串配置缺失:Mongo root账号默认在admin库下创建,原连接串未指定authSource=admin参数,驱动会默认在业务库下查找用户,直接导致认证失败。
修复实现

1. 调整服务端代码逻辑

把HTTP服务启动逻辑放到Mongo连接成功的回调中,补充完整错误处理,连接失败直接打印日志退出进程方便排查:

'use strict'

const express = require('express');
const { MongoClient } = require('mongodb');

// 补充authSource=admin指定认证库,直接写入要连接的业务库
const url = 'mongodb://toor:root@mongodbdatabase:27017/mongodbdatabase?authSource=admin';

const app = express();
const PORT = 8080;
const HOST = '0.0.0.0';

const client = new MongoClient(url);

app.use('/', express.static('public'));

app.get('/createDatabase', async (req, res) => {
  try {
    const db = client.db('mongodbdatabase');
    await db.createCollection("HiveDB");
    console.log("Collection Created");
    res.send('Collection created successfully');
  } catch (err) {
    console.error('Create collection failed:', err);
    res.status(500).send('Internal server error');
  }
})

// 先建立数据库连接,确认连通后再启动HTTP服务
async function startServer() {
  try {
    await client.connect();
    // 发送ping命令验证连接可用性
    await client.db().command({ ping: 1 });
    console.log("Connected to MongoDB successfully");

    app.listen(PORT, HOST, () => {
      console.log(`Listening on port ${PORT}`);
    });
  } catch (err) {
    console.error('Failed to connect to MongoDB:', err);
    process.exit(1);
  }
}

startServer();

2. 优化Docker配置

锁定基础镜像和依赖版本避免无感知升级,给Mongo服务增加健康检查,确认服务就绪后再启动Node服务:
修改后的Dockerfile:

# 锁定Node大版本,禁止使用latest
FROM node:18-bullseye

EXPOSE 8080

WORKDIR /usr/src/app

# 优先复制依赖配置文件,复用Docker构建缓存
COPY package*.json ./
# 使用npm ci按锁文件安装依赖,避免版本漂移
RUN npm ci --omit=dev
RUN npm install -g loadtest

COPY server.js /usr/src/app/server.js
COPY /public /usr/src/app/public

CMD ["node", "server.js"]

修改后的docker-compose.yml:

version: '3'
services:

  mainserver:
    build: ./main
    depends_on:
      mongodbdatabase:
        # 等待Mongo健康检查通过后再启动
        condition: service_healthy
    container_name: mainServer
    ports:
      - "83:8080"
    # 异常退出自动重启
    restart: on-failure


  mongodbdatabase:
    # 锁定Mongo大版本
    image: mongo:6
    container_name: monDataBase
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: toor
      MONGO_INITDB_ROOT_PASSWORD: root
    # 配置健康检查,确认Mongo可正常响应
    healthcheck:
      test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
      interval: 5s
      timeout: 5s
      retries: 10

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:03:29