跨主机连接MongoDB时Mongoose返回undefined问题求助
问题分析与解决方案
核心问题排查
你的代码在主机2运行返回undefined,主要有以下几个原因:
- 重复注册Model:每次调用
get函数都重新创建Schema和Model,Mongoose不允许重复注册同名Model,会导致Model实例失效,无法正常查询。 - 类型不匹配:查询时传入的
ID是数字3,但Schema中id定义为String类型,MongoDB查询严格匹配类型,因此找不到对应文档;新创建实例时如果传入数字ID,存储后类型不一致也会导致后续查询异常。 - 未复用数据库连接:每次调用都重新发起连接,可能连接未完成就执行查询,导致无结果返回。
- 未处理连接错误:连接失败时没有捕获异常,无法排查连接问题。
修正后的代码实现
把Schema、Model定义和数据库连接逻辑抽离,复用资源,同时处理类型转换和错误:
1. 抽离Model定义(主机1和主机2共用)
创建userModel.js:
const mongoose = require('mongoose'); // 仅定义一次Schema const UserSchema = new mongoose.Schema({ id: { type: String, unique: true, required: true }, money: { type: Number, default: 0 } }); // 避免重复注册Model,优先使用已存在的Model const User = mongoose.models.User || mongoose.model('User', UserSchema); module.exports = User;
2. 抽离数据库连接逻辑(主机1和主机2共用)
创建db.js:
const mongoose = require('mongoose'); // 替换为你的数据库连接URI,主机2要写主机1的IP,比如 mongodb://主机1IP:27017/你的数据库名 const uri = '你的MongoDB连接URI'; // 复用已有的连接,避免重复连接 async function connectDB() { // 已连接则直接返回 if (mongoose.connection.readyState === 1) return; try { await mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }); console.log('数据库连接成功'); } catch (err) { console.error('数据库连接失败:', err); throw err; } } module.exports = connectDB;
3. 主业务逻辑代码
const connectDB = require('./db'); const User = require('./userModel'); async function get(ID) { try { await connectDB(); // 将数字ID转为String,匹配Schema定义 const person = await User.findOne({ id: String(ID) }) || new User({ id: String(ID) }); console.log(person.money); // 新创建的实例需要保存到数据库 if (person.isNew) { await person.save(); } return person; } catch (err) { console.error('查询操作失败:', err); } } get(3);
主机2额外注意事项
- 确保主机1的MongoDB服务允许主机2的IP访问,防火墙开放27017端口(默认端口)。
- 连接URI中的主机地址填写主机1的公网IP(跨网络)或内网IP(同一局域网)。
- 主机2安装的mongoose版本与主机1保持一致,避免版本兼容性问题。
内容的提问来源于stack exchange,提问作者Liman
相关产品推荐
相关产品推荐

