许多人问:在Nodejs中如何共享Mongoose建立一个数据库连接,然后在此应用程序其它地方都使用这个数据库连接?
许多国外的帖子对此进行了讨论,但是国内相对沉闷,技术的流行程度和对技术的热衷度也可见一斑。
Anyway....回到主题
下面这个例子告诉大家如何实现建立一个数据库连接之后在程序的其它地方都使用它。
例子基于Express, 按照以下步骤生成Express的目录结构并安装必要的包
1. npm install -g express-generator
2. md mytest && cd mytest (建立一个目录,并进入目录)
3. express -e (生成网站的目录结构,-e 表示用ejs 作为模板,默认模板是jade)
4. npm install -d (安装依赖项)
5. npm install mongoose
基于Express做这个例子的原因是我想用Express中的路由,仅此而已
顺便提一句,大家都用什么编辑器写Nodejs代码?我用Sublime Text 2, 很好用。
在这个例子里,我们往数据库中插入新公司(company集合)和新国家(country集合)我们会建立一个Mongoose的数据库连接,然后在任何地方都用它。
我们把代码用文件夹归类,首先在mytest目录下建util目录,在util目录下建schema目录和dal目录,schema目录用来存放定义的schema,dal目录用来存放最终写数据库的代码
建好之后的目录结构如下图:
然后在dal目录下建db.js文件,在db.js中会建立到数据库的连接,代码如下:
var mongoose=require(‘mongoose‘);console.log(‘Creating global mongoose connection...‘);
// Build the connection string
var dbURI = ‘mongodb://localhost:27017/mytest‘;// Create the database connection
mongoose.connect(dbURI);// CONNECTION EVENTS
// When successfully connected
mongoose.connection.on(‘connected‘, function () {
console.log(‘Mongoose default connection open to ‘ + dbURI);
});// If the connection throws an error
mongoose.connection.on(‘error‘,function (err) {
console.log(‘Mongoose default connection error: ‘ + err);
});// When the connection is disconnected
mongoose.connection.on(‘disconnected‘, function () {
console.log(‘Mongoose default connection disconnected‘);
});// If the Node process ends, close the Mongoose connection
process.on(‘SIGINT‘, function() {
mongoose.connection.close(function () {
console.log(‘Mongoose default connection disconnected through app termination‘);
process.exit(0);
});
});module.exports=mongoose;
注意最后一句,这里将mongoose对象作为此模块的输出,以便在其它地方使用它。
下面我们来定义schema,这里就会用到db.js。
先定义company的schema,代码如下:
var mongoose=require(‘../dal/db.js‘);
var Schema=mongoose.Schema;var companySchema=new Schema({
Name:String
});module.exports=mongoose.model(‘Company‘,companySchema);
然后定义country的schema,代码如下:
var mongoose=require(‘../dal/db.js‘);
var Schema=mongoose.Schema;var countrySchema=new Schema({
Name:String
});module.exports=mongoose.model(‘Country‘,countrySchema);
注意,以上两个模块的输出是model对象。
现在来写插入数据库的代码。
在dal文件夹中,新建companyDAL.js文件,代码如下:
var Company=require(‘../schema/company.js‘);exports.create=function(data,callback){
var company=new Company({
Name:data.name
});
company.save(function(err,company){
if(!err){
callback(null,company);
}
else{
callback(err,null);
}
});
};
在dal文件夹中,新建countryDAL.js文件,代码如下:
var Country=require(‘../schema/country.js‘);exports.create=function(data,callback){
var country=new Country({
Name:data.name
});
country.save(function(err,country){
if(!err){
callback(null,country);
}
else{
callback(err,null);
}
});
};
好了,现在是测试插入数据的时候了,方便起见,我们定义两个路由:
一个路由在GET /company的时候插入一条数据到company集合
一个路由在GET /country的时候插入一条数据到country集合
在routes目录下,新建company.js文件,代码如下:
var express = require(‘express‘);
var router = express.Router();
var companyDAL=require(‘../util/dal/companyDAL‘);router.get(‘/‘, function(req, res) {
companyDAL.create({"name":"My Company"},function(err,result){
if(!err){
res.send(JSON.stringify(result));
}
else{
res.send(err);
}
});
});module.exports = router;
在routes目录下,新建country.js文件,代码如下:
var express = require(‘express‘);
var router = express.Router();
var countryDAL=require(‘../util/dal/countryDAL‘);router.get(‘/‘, function(req, res) {
countryDAL.create({"name":"My Country"},function(err,result){
if(!err){
res.send(JSON.stringify(result));
}
else{
res.send(err);
}
});
});module.exports = router;
然后回到app.js文件添加这两个路由:
var routes = require(‘./routes/index‘);
var users = require(‘./routes/users‘);
var company=require(‘./routes/company‘);
var country=require(‘./routes/country‘);...............................
app.use(‘/‘, routes);
app.use(‘/users‘, users);
app.use(‘/company‘,company);
app.use(‘/country‘,country);
最终的文件目录结构如下图:
现在我们来测试一下:
在命令行里输入:node bin/www,可以看到下图
提示信息来自db.js,至此表明数据库已经连接成功(请各位看官记得先用mongod启动数据库)
用浏览器访问 http://http://localhost:3000/company
用浏览器访问 http://localhost:3000/country
可以看到如下的输出:
表明数据插入成功。
下面总结一下:
1. 从代码以及结果可见,在往company和country数据集插入数据的时候,都是使用的db.js中定义mongoose对象
2. db.js 在 node bin/www启动应用程序的时候就被执行,为什么会被执行?
因为app.js中定义了路由并作为中间件使用
var company=require(‘./routes/company‘);var country=require(‘./routes/country‘);
......................
app.use(‘/company‘,company);
app.use(‘/country‘,country);
然后又在路由文件(routes/company.js, routes/country.sj)中引用了数据访问层的代码
var companyDAL=require(‘../util/dal/companyDAL‘);var countryDAL=require(‘../util/dal/countryDAL‘);
在companyDAL.js和countryDAL中又引用了schema的代码
var Company=require(‘../schema/company.js‘);var Country=require(‘../schema/country.js‘);
在schema代码中引用了db.js
var mongoose=require(‘../dal/db.js‘);
所以在程序启动的时候db.js被调用,并且,db.js无论被引用了多少次,只会被调用一次,这是require机制决定的。
因此实现Mongoose全局数据库连接的原理是在程序启动的时候我们就定义好数据库连接,并打开数据库连接,并把此mongoose对象作为模块的导出,其它需要使用数据库连接的时候,直接require这个模块就可以了