阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 连接MongoDB数据库

连接MongoDB数据库

作者:陈川 阅读数:8207人阅读 分类: MongoDB

连接MongoDB数据库

MongoDB作为流行的NoSQL数据库,与Node.js生态的Mongoose库搭配使用能极大简化数据操作。通过Mongoose连接MongoDB需要理解连接字符串、连接选项和连接事件等核心概念。

基本连接方式

最简单的连接方式只需要提供MongoDB的URI:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydatabase')
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('Connection error:', err));

连接字符串格式通常为mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[database][?options]]。当需要认证时:

mongoose.connect('mongodb://user:pass@localhost:27017/mydatabase?authSource=admin');

连接选项配置

Mongoose支持丰富的连接选项:

const options = {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  poolSize: 10, // 连接池大小
  connectTimeoutMS: 5000, // 连接超时
  socketTimeoutMS: 45000, // socket超时
  family: 4, // 强制IPv4
  authSource: 'admin',
  user: 'myUser',
  pass: 'myPassword'
};

mongoose.connect('mongodb://localhost:27017/mydatabase', options);

重要选项说明:

  • useNewUrlParser: 使用新的URL解析器
  • useUnifiedTopology: 使用新的拓扑引擎
  • autoIndex: 是否自动创建索引(生产环境建议false)

连接池优化

连接池管理对性能至关重要:

const options = {
  poolSize: 20, // 默认5
  maxPoolSize: 100, // 连接池最大数量
  minPoolSize: 10, // 连接池最小数量
  serverSelectionTimeoutMS: 5000, // 服务器选择超时
  heartbeatFrequencyMS: 10000 // 心跳检测频率
};

监控连接池状态:

mongoose.connection.on('connected', () => {
  console.log(`Mongoose default connection pool size: ${mongoose.connection.poolSize}`);
});

多数据库连接

实际项目经常需要连接多个数据库:

const db1 = mongoose.createConnection('mongodb://localhost:27017/db1');
const db2 = mongoose.createConnection('mongodb://localhost:27017/db2');

db1.on('open', () => console.log('DB1 connected'));
db2.on('open', () => console.log('DB2 connected'));

// 使用不同连接创建模型
const User = db1.model('User', userSchema);
const Product = db2.model('Product', productSchema);

连接事件处理

Mongoose连接生命周期事件:

mongoose.connection.on('connecting', () => {
  console.log('尝试连接MongoDB...');
});

mongoose.connection.on('connected', () => {
  console.log('MongoDB连接成功');
});

mongoose.connection.on('disconnected', () => {
  console.log('MongoDB连接断开');
});

mongoose.connection.on('reconnected', () => {
  console.log('MongoDB重新连接');
});

mongoose.connection.on('error', (err) => {
  console.error('MongoDB连接错误:', err);
});

连接重试策略

网络不稳定时需要自动重连:

const options = {
  autoReconnect: true, // 已废弃,新版本默认启用
  reconnectTries: Number.MAX_VALUE, // 无限重试
  reconnectInterval: 1000 // 重试间隔
};

function connectWithRetry() {
  return mongoose.connect(uri, options)
    .catch(err => {
      console.error('连接失败,5秒后重试:', err.message);
      return new Promise(resolve => 
        setTimeout(() => connectWithRetry().then(resolve), 5000)
      );
    });
}

TLS/SSL连接

安全连接配置示例:

const fs = require('fs');

const options = {
  ssl: true,
  sslValidate: true,
  sslCA: fs.readFileSync('./ca.pem'),
  sslCert: fs.readFileSync('./client.pem'),
  sslKey: fs.readFileSync('./client.key'),
  sslPass: 'yourpassphrase'
};

mongoose.connect(uri, options);

连接状态检查

实用工具函数示例:

function checkConnectionState() {
  const states = {
    0: '断开',
    1: '已连接',
    2: '连接中',
    3: '断开中',
    99: '未初始化'
  };
  return states[mongoose.connection.readyState];
}

// 使用示例
console.log(`当前连接状态: ${checkConnectionState()}`);

连接性能优化

生产环境推荐配置:

const prodOptions = {
  autoIndex: false, // 生产环境禁用自动索引
  bufferCommands: false, // 禁用缓冲
  bufferMaxEntries: 0, // 禁用缓冲条目
  useCreateIndex: true, // 使用createIndex()替代ensureIndex()
  useFindAndModify: false // 使用原生findOneAndUpdate()
};

连接字符串高级用法

分片集群连接示例:

const shardUri = 'mongodb://mongos1.example.com:27017,mongos2.example.com:27017/dbname?replicaSet=shard-rs';

Atlas云数据库连接:

const atlasUri = 'mongodb+srv://cluster0.mongodb.net/dbname?retryWrites=true&w=majority';

连接调试

启用调试模式查看详细日志:

mongoose.set('debug', true);
// 或自定义调试函数
mongoose.set('debug', (collectionName, method, query, doc) => {
  console.log(`${collectionName}.${method}`, JSON.stringify(query), doc);
});

连接关闭

正确关闭连接的方式:

async function gracefulShutdown() {
  await mongoose.connection.close();
  console.log('MongoDB连接已关闭');
  process.exit(0);
}

process.on('SIGINT', gracefulShutdown);
process.on('SIGTERM', gracefulShutdown);

连接中间件

使用插件扩展连接功能:

// 定义插件
function connectionLogger(schema) {
  schema.post('init', doc => {
    console.log(`文档从MongoDB初始化: ${doc._id}`);
  });
}

// 应用到连接
mongoose.plugin(connectionLogger);

连接最佳实践

  1. 使用环境变量管理连接配置:
require('dotenv').config();

mongoose.connect(process.env.MONGODB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});
  1. 实现健康检查端点:
app.get('/health', (req, res) => {
  if (mongoose.connection.readyState === 1) {
    res.status(200).json({ status: 'OK' });
  } else {
    res.status(503).json({ status: 'DB disconnected' });
  }
});
  1. 连接超时处理:
const connectWithTimeout = async () => {
  const timeout = setTimeout(() => {
    throw new Error('数据库连接超时');
  }, 5000);
  
  await mongoose.connect(uri);
  clearTimeout(timeout);
};

连接问题排查

常见错误处理:

mongoose.connect(uri).catch(err => {
  if (err.name === 'MongoNetworkError') {
    console.error('网络问题:', err.message);
  } else if (err.name === 'MongooseServerSelectionError') {
    console.error('服务器选择失败:', err.message);
  } else if (err.name === 'MongoError' && err.code === 18) {
    console.error('认证失败:', err.message);
  }
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌