连接(Connections)
你可以使用 mongoose.connect()
方法连接 MongoDB 。
mongoose.connect('mongodb://localhost/myapp');
这是连接到本地 myapp
数据库默认接口(27017)的最小配置。 本地连接失败可以尝试连接 127.0.0.1 。 local hostname 被修改有时候会引起问题。
你也可以在 uri
中指定多个参数:
mongoose.connect('mongodb://username:password@host:port/database?options...');
详情请看 mongodb connection string spec for more detail.
操作缓存
你不必等待连接建立成功就可以使用你的 Mongoose models 。
mongoose.connect('mongodb://localhost/myapp');
var MyModel = mongoose.model('Test', new Schema({ name: String }));
// 可行
MyModel.findOne(function(error, result) { /* ... */ });
Mongoose 会缓存你的 model 操作。这个操作很方便,但也回引起一些疑惑, 因为如果你没连上 ,Mongoose 不会 抛错。
var MyModel = mongoose.model('Test', new Schema({ name: String }));
// 连接成功前操作会被挂起
MyModel.findOne(function(error, result) { /* ... */ });
setTimeout(function() {
mongoose.connect('mongodb://localhost/myapp');
}, 60000);
要禁用缓存,请修改 bufferCommands
配置。 如果你打开了 bufferCommands
连接被挂起,尝试关闭 bufferCommands
检查你是否正确打开连接。 你也可以全局禁用 bufferCommands
:
mongoose.set('bufferCommands', false);
选项
connect
方法也接受 options
参数,这些参数会传入底层 MongoDB 驱动。
mongoose.connect(uri, options);
完整参数列表请参考 MongoDB Node.js 驱动文档 connect()
。 Mongoose 会不做修改直接把选项传到驱动,以下有一点例外
bufferCommands
- 这是 mongoose 特有的选项 (不传到 MongoDB) ,禁用 mongoose 缓存机制user
/pass
- 用于认证的用户名和密码。mongoose 特有,等价于 MongoDB 驱动的auth.user
和auth.password
选项autoIndex
- 默认情况下,mongoose 在连接时会自动建立 schema 的索引。这有利于开发,但是在大型生产环境下不是十分理想,因为索引建立会导致性能下降。如果autoIndex
设为 false,mongoose 将不会自动建立索引dbName
- 指定要连接的数据库名称(覆盖连接字符串)。 如果你使用mongodb+srv
语法连接 MongoDB Atlas, 你 需要使用dbName
指定数据库
以下是一些重要选项
autoReconnect
- 底层 MongoDB 驱动在连接丢失后将自动重连。除非你是可以自己管理连接池的高手,否则不要把这个选项设为false
reconnectTries
- If you're connected to a single server or mongos proxy (as opposed to a replica set), the MongoDB driver will try to reconnect everyreconnectInterval
milliseconds forreconnectTries
times, and give up afterward. When the driver gives up, the mongoose connection emits areconnectFailed
event. This option does nothing for replica set connections.reconnectInterval
- 见reconnectTries
promiseLibrary
- 设定底层 promise 库poolSize
- MongoDB 保持的最大 socket 连接数。poolSize
的默认值是 5。注意,MongoDB 3.4 之前, MongoDB 只允许每个 socket 同时进行一个操作,所以如果你有几个缓慢请求卡着后面快的请求,可以尝试增加连接数。bufferMaxEntries
- MongoDB 驱动同样有自己的离线时缓存机制。如果你希望链接错误时终止数据库操作,请将此选项设为 0 以及把bufferCommands
设为false
。
举例:
const options = {
useMongoClient: true,
autoIndex: false, // Don't build indexes
reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0
};
mongoose.connect(uri, options);
回调
connect()
函数接受回调函数,或返回一个 promise。
mongoose.connect(uri, options, function(error) {
// Check error in initial connection. There is no 2nd param to the callback.
});
// Or using promises
mongoose.connect(uri, options).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ },
err => { /** handle initial connection error */ }
);
连接字符串( Connection String )选项
你也可以在连接字符串填写驱动选项,但是这只适用于 MongoDB 驱动使用的选项, 所以类似 bufferCommands
的 Mongoose 专用选项不能在连接字符串使用。
mongoose.connect('mongodb://localhost:27017/test?connectTimeoutMS=1000&bufferCommands=false');
// The above is equivalent to:
mongoose.connect('mongodb://localhost:27017/test', {
connectTimeoutMS: 1000
// Note that mongoose will **not** pull `bufferCommands` from the query string
});
把选项放在连接字符串的劣势是不便于阅读,优势是你只需要写一条连接而不需要把所有设定分开写。 最佳实践是把区分生产环境和开发环境的选项如 socketTimeoutMS
、 connectTimeoutMS
放在 uri , 把通用的常量如 connectTimeoutMS
、 poolSize
放在选项对象里。
MongoDB 的文档可以找到关于连接字符串的所有选项。
keepAlive 注意事项
对于长期运行的后台应用,启用毫秒级 keepAlive
是一个精明的操作。不这么做你可能会经常 收到看似毫无原因的 "connection closed"
错误。遇到这个情况, 阅读这篇文章, 你或许会立刻启用 keepAlive
:
mongoose.connect(uri, { keepAlive: 120 });
副本集(Replica Set)连接
要连接到副本集,你可以用逗号分隔,传入多个地址。
mongoose.connect('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]);
连接到单节点副本集,需指定 replicaSet
选项。
mongoose.connect('mongodb://host1:port1/?replicaSet=rsName');
多 mongos 支持
使用高性能分片集群,需要连接多个 mongos(MongoDB Shard) 实例。 在 mongoose 5.x 中, 你在连接多个 mongos 时不需要传入任何特殊选项。
// Connect to 2 mongos servers
mongoose.connect('mongodb://mongosA:27501,mongosB:27501', cb);
多个连接
之前我们了解如何使用 Mongoose 默认连接方法连接到 MongoDB。但有时候我们需要权限不同的多个连接, 或是连接到不同数据库。这个情况下我们可以使用 mongoose.createConnection()
, 它接受之前提到的所有参数,给你返回一个新的连接。
const conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options);
connection 对象后续用于创建和检索 models。 models 的范围总是局限于单个连接。
调用 mongoose.connect()
时,Mongoose 会自动创建默认连接。 你可以使用 mongoose.connection
访问默认连接。
连接池
无论是使用 mongoose.connect
或是 mongoose.createConnection
创建的连接, 都被纳入默认最大为 5 的连接池,可以通过 poolSize 选项调整:
// With object options
mongoose.createConnection(uri, { poolSize: 4 });
const uri = 'mongodb://localhost/test?poolSize=4';
mongoose.createConnection(uri);
v5.x 的变化
从 4.x 升级到 5.x,你可能会看到一下弃用提示, 你不应该在 4.x 使用 useMongoClient
选项:
the server/replset/mongos options are deprecated, all their options are supported at the top level of the options object
旧版的 MongoDB 驱动中你需要为多连接配置特定选项:
mongoose.connect(myUri, {
server: {
socketOptions: {
socketTimeoutMS: 0,
keepAlive: true
},
reconnectTries: 30
},
replset: {
socketOptions: {
socketTimeoutMS: 0,
keepAlive: true
},
reconnectTries: 30
},
mongos: {
socketOptions: {
socketTimeoutMS: 0,
keepAlive: true
},
reconnectTries: 30
}
});
mongoose v5.x 中,你可以把所有选项写在顶层而不用嵌套到每个属性。 点击这里查看所有选项列表。
// Equivalent to the above code
mongoose.connect(myUri, {
socketTimeoutMS: 0,
keepAlive: true,
reconnectTries: 30
});
下一步
现在我们介绍了 mongoose 的连接方式,接着看看 models。