我在尝试访问MongoDB客户端模块连接到MongoDB数据库时创建的“DB”数据库对象时遇到问题。
目前我收到一条错误,指出在data.js中,未定义“db”。我理解为什么这样 - 数据库对象没有被“传递”到路由器然后再传递到控制器。
这样做的最佳方式是什么?
我试图将“db”对象传递给路由器(dataRoutes.js),但我无法想象如何使控制器(data.js)可以访问它。有人可以帮忙吗?
请注意我没有包括其他路线和控制器,但他们只需通过POST方法将表格提交至/ data / submit。下面的控制器用于将此表单数据写入MongoDB数据库。
以下是相关代码:
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) throw err;
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
app.use(function(req, res, next) {
var err = new Error('Oops Page/Resource Not Found!');
err.status = 404;
next(err); //Proceed to next middleware
});
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
// update the error responce, either with the error status
// or if that is falsey use error code 500
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
console.log('Error');
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
});
dataRoutes.js
// router
var express = require('express');
var router = express.Router();
// controller references
var ctrlsData = require('../controllers/data');
router.post('/submit', ctrlsData.submit);
module.exports = router;
data.js
var MongoClient = require('mongodb').MongoClient;
var sendJsonResponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.submit = function(req, res) {
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
/*
console.log('submitted');
console.log(req.body);
sendJsonResponse(res, 201, {title,year,imdb});
*/
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
if ((title == '') || (year == '') || (imdb == '')) {
sendJsonResponse(res, 404, {
"message": "Title, Year and IMDB Reference are all required."
});
} else {
db.collection('movies').insertOne(
{ 'title': title, 'year': year, 'imdb': imdb },
function (err, r) {
if (err) {
sendJsonResponse(res, 400, err);
} else {
sendJsonResponse(res, 201, "Document inserted with _id: " + r.insertedId + {title,year,imdb});
}
}
);
}
};
答案 0 :(得分:9)
在db
中创建一个引用mongodb的app.js
变量:
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
app.db = db;
//.....
});
在data.js
中,从db
访问req.app
:
module.exports.submit = function(req, res) {
req.app.db.collection('movies').insertOne({ 'title': title, 'year': year, 'imdb': imdb },
function(err, r) {}
)
};
答案 1 :(得分:2)
接受的答案不太正确。您不应将自定义对象附加到app
对象。这就是app.locals
的目的。另外,使用打字稿时,接受的答案将失败。
app.locals.db = db;
router.get('/foo', (req) => {
req.app.locals.db.insert('bar');
});
当然,它会更长一些,但是您可以确保将来对ExpressJS的更新永远不会干扰您的对象。
答案 2 :(得分:0)
我知道@Bertrand的答案是实用的,但通常不建议这样做。原因是,从软件的角度来看,您应该在软件中实现更好的分离。
$sql = "INSERT INTO Game_table (Email,Card_no,Table_no,Token_key,Bet_amount)
VALUES ('$Emails', '$Cards', '$Table', '$Token_key', '$Bet_amount');";
//2nd query Notice this ------------------------------------^
$sql .= " UPDATE LaborRegistered SET balance = balance - '$Bet_amount' WHERE Phone_no ='$Emails';";
if ($conn->multi_query($sql) === true)
{
// ...
}
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
var DB = require('./db.js');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
DB.Init("mongodb://localhost:27017/m101")
.then(() => {
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
})
.catch((e) => {
console.log("Error initializing db");
});
db.js
在var _db = null;
module.exports = {
Init: (url) => {
return new Promise((resolve, reject) => {
if (!url)
reject("You should provide a URL");
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) reject(err);
_db = db;
resolve(); // Or resolve(db) if you wanna return the db object
});
});
},
Submit: (req, res, next) => {
// Whatever goes. You have access to _db here, too!
}
};
data.js
最后,甚至可以改善此答案,因为通常不建议您等待数据库连接,否则,您将失去使用ASync procs的优势。
考虑类似于var DB = require('../db.js');
router.post('/submit', DB.submit);
中的here的事物:
app.js
我了解在上一个示例中,由于它可能尚未连接,因此无法立即查询数据库,但这是一台服务器,通常希望用户等待数据库初始化。但是,如果您想要更多的证明解决方案,请考虑自己在Promise.resolve()
.then(() => {
// Whatever DB stuff are
// DB.Init ?
})
.then(() => {
// Someone needs routing?
})
...
.catch((e) => {
console.error("Ther app failed to start");
console.error(e);
});
中实现某些功能以等待连接。或者,您也可以使用类似mongoose的东西。