Docker部署Express应用调用MongoDB时遇TypeError问题求助
问题描述
在Docker上运行Express应用时,访问localhost:3000/createMongo或localhost:3000/readMongo会触发以下错误:
TypeError: Cannot read properties of undefined (reading 'collection') at /app/index.js:24:25 at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at next (/app/node_modules/express/lib/router/route.js:144:13) at Route.dispatch (/app/node_modules/express/lib/router/route.js:114:3) at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at /app/node_modules/express/lib/router/index.js:284:15 at Function.process_params (/app/node_modules/express/lib/router/index.js:346:12) at next (/app/node_modules/express/lib/router/index.js:280:10) at expressInit (/app/node_modules/express/lib/middleware/init.js:40:5) at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
补充说明:访问localhost:3000可正常显示Greetings from the server!!,控制台也输出Connected correctly to server!!,推测是MongoDB更新后语法不兼容导致。
原index.js代码:
var express = require('express'); var app = express(); var MongoClient = require('mongodb').MongoClient; // the name "mongo" comes from the docker link, in the docker-compose.yml var url = 'mongodb://mongo:27017/dockerdemo'; var db; MongoClient.connect(url, function (err, database) { if(err){ console.log('failed to connect: ' + err); return;} db = database; console.log("Connected correctly to server!!"); }); app.get('/', function(req, res){ res.send('Greetings from the server!!'); }); app.get('/createMongo', function(req, res){ var name = 'user' + Math.floor(Math.random()*10000); var email = name + '@mit.edu'; var collection = db.collection('customers'); var doc = {'name':name, 'email':email}; collection.insert(doc, {w:1}, function(err, result) { console.dir(result); res.send(result); }); }); app.get('/readMongo', function(req, res){ var results = null; var collection = db .collection('customers') .find() .toArray(function(err, docs) { console.dir(docs); res.send(docs); }); }); app.listen(3000);
问题排查与解决
错误原因
- MongoDB驱动版本兼容问题:MongoDB Node.js驱动v3+版本中,
MongoClient.connect的回调参数不再直接返回数据库实例,而是返回客户端对象,需要通过client.db()获取目标数据库。原代码直接将回调的database赋值给db,实际拿到的是客户端对象,并非数据库实例,导致调用db.collection()时出错。 - 弃用API使用:
collection.insert()方法已被弃用,需替换为insertOne(单文档插入)或insertMany(多文档插入)。 - 连接未就绪时的请求风险:原代码未处理MongoDB连接完成前的请求,若在连接建立前访问
/createMongo或/readMongo,db变量仍为undefined,也会触发错误。
修复后的代码
var express = require('express'); var app = express(); var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://mongo:27017/dockerdemo'; var db; // 修正连接逻辑,获取正确的数据库实例 MongoClient.connect(url, function (err, client) { if(err){ console.log('failed to connect: ' + err); return; } // 通过client.db()获取目标数据库 db = client.db('dockerdemo'); console.log("Connected correctly to server!!"); }); app.get('/', function(req, res){ res.send('Greetings from the server!!'); }); app.get('/createMongo', function(req, res){ // 增加db存在性校验 if (!db) { return res.status(500).send('Database connection not ready'); } var name = 'user' + Math.floor(Math.random()*10000); var email = name + '@mit.edu'; var collection = db.collection('customers'); var doc = {'name':name, 'email':email}; // 替换弃用的insert为insertOne collection.insertOne(doc, function(err, result) { if (err) { console.error(err); return res.status(500).send('Failed to insert document'); } console.dir(result); res.send(result); }); }); app.get('/readMongo', function(req, res){ // 增加db存在性校验 if (!db) { return res.status(500).send('Database connection not ready'); } db.collection('customers') .find() .toArray(function(err, docs) { if (err) { console.error(err); return res.status(500).send('Failed to fetch documents'); } console.dir(docs); res.send(docs); }); }); app.listen(3000);
关键修改点
- 连接MongoDB时,从客户端对象
client中通过client.db('dockerdemo')获取数据库实例,赋值给db变量。 - 将
collection.insert()替换为collection.insertOne(),适配新版驱动API。 - 在
/createMongo和/readMongo路由中增加db存在性校验,返回明确的错误信息,避免未连接时的崩溃。
内容的提问来源于stack exchange,提问作者Sar
相关产品推荐
相关产品推荐

