나는 읽고 읽고 있었지만 전체 NodeJs 앱에서 동일한 데이터베이스 (MongoDb) 연결을 공유하는 가장 좋은 방법이 무엇인지 여전히 혼란 스럽습니다. 내가 이해했듯이 앱이 시작될 때 연결이 열리고 모듈간에 재사용되어야합니다. 현재 가장 좋은 방법은 server.js
(모든 것이 시작되는 주 파일) 데이터베이스에 연결하고 모듈에 전달되는 개체 변수를 만드는 것입니다. 일단 연결되면이 변수는 필요에 따라 모듈 코드에서 사용되며이 연결은 열린 상태로 유지됩니다. 예 :
var MongoClient = require('mongodb').MongoClient;
var mongo = {}; // this is passed to modules and code
MongoClient.connect("mongodb://localhost:27017/marankings", function(err, db) {
if (!err) {
console.log("We are connected");
// these tables will be passed to modules as part of mongo object
mongo.dbUsers = db.collection("users");
mongo.dbDisciplines = db.collection("disciplines");
console.log("aaa " + users.getAll()); // displays object and this can be used from inside modules
} else
console.log(err);
});
var users = new(require("./models/user"))(app, mongo);
console.log("bbb " + users.getAll()); // not connected at the very first time so displays undefined
다른 모듈 models/user
은 다음과 같습니다.
Users = function(app, mongo) {
Users.prototype.addUser = function() {
console.log("add user");
}
Users.prototype.getAll = function() {
return "all users " + mongo.dbUsers;
}
}
module.exports = Users;
이제 나는 이것이 잘못되었다는 끔찍한 느낌이 들기 때문에이 접근 방식에 명백한 문제가 있습니까? 그렇다면 어떻게 더 좋게 만들 수 있습니까?
답변
mongoUtil.js
mongo에 연결하고 mongo db 인스턴스를 반환하는 기능이 있는 모듈을 만들 수 있습니다 .
const MongoClient = require( 'mongodb' ).MongoClient;
const url = "mongodb://localhost:27017";
var _db;
module.exports = {
connectToServer: function( callback ) {
MongoClient.connect( url, { useNewUrlParser: true }, function( err, client ) {
_db = client.db('test_db');
return callback( err );
} );
},
getDb: function() {
return _db;
}
};
그것을 사용하려면 다음에서 수행하십시오 app.js
.
var mongoUtil = require( 'mongoUtil' );
mongoUtil.connectToServer( function( err, client ) {
if (err) console.log(err);
// start the rest of your app here
} );
그런 다음 다른 .js
파일 과 같이 다른 곳에서 mongo에 액세스해야 할 때 다음 을 수행 할 수 있습니다.
var mongoUtil = require( 'mongoUtil' );
var db = mongoUtil.getDb();
db.collection( 'users' ).find();
이 작품 그 이유는 모듈이 때 노드에 있다는 것입니다 require
‘D, 그들은 단지 당신이 오직의 하나 개의 인스턴스로 끝날 것 때문에 일단 소스 /로드되는 _db
및 mongoUtil.getDb()
항상 같은 인스턴스를 반환합니다.
코드는 테스트되지 않았습니다.
답변
여러 가지 방법으로 구성 객체를 수용하도록 조정할 수 있지만 전반적으로 코드를 배치하는 방법과 비슷하지만 더 현대적인 JS 구문을 사용합니다. 필요하다면 프로토 타입과 콜백으로 쉽게 다시 작성할 수 있습니다.
mongo.js
const { MongoClient } = require('mongodb');
const config = require('./config');
const Users = require('./Users');
const conf = config.get('mongodb');
class MongoBot {
constructor() {
const url = `mongodb://${conf.hosts.join(',')}`;
this.client = new MongoClient(url, conf.opts);
}
async init() {
await this.client.connect();
console.log('connected');
this.db = this.client.db(conf.db);
this.Users = new Users(this.db);
}
}
module.exports = new MongoBot();
Users.js
class User {
constructor(db) {
this.collection = db.collection('users');
}
async addUser(user) {
const newUser = await this.collection.insertOne(user);
return newUser;
}
}
module.exports = User;
app.js
const mongo = require('./mongo');
async function start() {
// other app startup stuff...
await mongo.init();
// other app startup stuff...
}
start();
someFile.js
const { Users } = require('./mongo');
async function someFunction(userInfo) {
const user = await Users.addUser(userInfo);
return user;
}
답변
go-oleg의 예를 기반으로 현대적인 구문으로 수행하는 방법은 다음과 같습니다. 광산은 테스트되고 작동합니다.
코드에 주석을 달았습니다.
./db/mongodb.js
const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://user:password@localhost:27017/dbName'
let _db
const connectDB = async (callback) => {
try {
MongoClient.connect(uri, (err, db) => {
_db = db
return callback(err)
})
} catch (e) {
throw e
}
}
const getDB = () => _db
const disconnectDB = () => _db.close()
module.exports = { connectDB, getDB, disconnectDB }
./index.js
// Load MongoDB utils
const MongoDB = require('./db/mongodb')
// Load queries & mutations
const Users = require('./users')
// Improve debugging
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at:', p, 'reason:', reason)
})
const seedUser = {
name: 'Bob Alice',
email: 'test@dev.null',
bonusSetting: true
}
// Connect to MongoDB and put server instantiation code inside
// because we start the connection first
MongoDB.connectDB(async (err) => {
if (err) throw err
// Load db & collections
const db = MongoDB.getDB()
const users = db.collection('users')
try {
// Run some sample operations
// and pass users collection into models
const newUser = await Users.createUser(users, seedUser)
const listUsers = await Users.getUsers(users)
const findUser = await Users.findUserById(users, newUser._id)
console.log('CREATE USER')
console.log(newUser)
console.log('GET ALL USERS')
console.log(listUsers)
console.log('FIND USER')
console.log(findUser)
} catch (e) {
throw e
}
const desired = true
if (desired) {
// Use disconnectDB for clean driver disconnect
MongoDB.disconnectDB()
process.exit(0)
}
// Server code anywhere above here inside connectDB()
})
./users/index.js
const ObjectID = require('mongodb').ObjectID
// Notice how the users collection is passed into the models
const createUser = async (users, user) => {
try {
const results = await users.insertOne(user)
return results.ops[0]
} catch (e) {
throw e
}
}
const getUsers = async (users) => {
try {
const results = await users.find().toArray()
return results
} catch (e) {
throw e
}
}
const findUserById = async (users, id) => {
try {
if (!ObjectID.isValid(id)) throw 'Invalid MongoDB ID.'
const results = await users.findOne(ObjectID(id))
return results
} catch (e) {
throw e
}
}
// Export garbage as methods on the Users object
module.exports = { createUser, getUsers, findUserById }
답변
Express를 사용 하는 경우 요청 객체에서 db 연결을 얻을 수있는 express-mongo-db 모듈을 사용할 수 있습니다.
설치
npm install --save express-mongo-db
server.js
var app = require('express')();
var expressMongoDb = require('express-mongo-db');
app.use(expressMongoDb('mongodb://localhost/test'));
route / users.js
app.get('/', function (req, res, next) {
req.db // => Db object
});
답변
go-oleg은 기본적으로 옳지 만, 요즘에는 (아마도) “mongodb”자체를 사용하지 않고 오히려 “더러운 작업”을 많이하는 프레임 워크를 사용합니다.
예를 들어 몽구스는 가장 일반적인 것 중 하나입니다. 이것은 우리의 초기 server.js
파일에있는 것입니다.
const mongoose = require('mongoose');
const options = {server: {socketOptions: {keepAlive: 1}}};
mongoose.connect(config.db, options);
이것이 설정에 필요한 모든 것입니다. 이제 코드의 어느 곳에서나 사용하십시오.
const mongoose = require('mongoose');
그리고 설정 한 인스턴스를 얻습니다. mongoose.connect
답변
약속으로 연결을 초기화하십시오.
const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection
그런 다음 데이터베이스에서 작업을 수행 할 때마다 연결을 호출합니다.
// if I want to insert into the database...
const connect = connection
connect.then(() => {
const doc = { id: 3 }
const db = client.db('database_name')
const coll = db.collection('collection_name')
coll.insertOne(doc, (err, result) => {
if(err) throw err
})
})
답변
허용 된 답변을 기반으로 테스트 된 솔루션 :
mongodbutil.js :
var MongoClient = require( 'mongodb' ).MongoClient;
var _db;
module.exports = {
connectToServer: function( callback ) {
MongoClient.connect( "<connection string>", function( err, client ) {
_db = client.db("<collection name>");
return callback( err );
} );
},
getDb: function() {
return _db;
}
};
app.js :
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
var mongodbutil = require( './mongodbutil' );
mongodbutil.connectToServer( function( err ) {
//app goes online once this callback occurs
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var companiesRouter = require('./routes/companies');
var activitiesRouter = require('./routes/activities');
var registerRouter = require('./routes/register');
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/companies', companiesRouter);
app.use('/activities', activitiesRouter);
app.use('/register', registerRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
//end of calback
});
module.exports = app;
activities.js-경로 :
var express = require('express');
var router = express.Router();
var mongodbutil = require( '../mongodbutil' );
var db = mongodbutil.getDb();
router.get('/', (req, res, next) => {
db.collection('activities').find().toArray((err, results) => {
if (err) return console.log(err)
res.render('activities', {activities: results, title: "Activities"})
});
});
router.post('/', (req, res) => {
db.collection('activities').save(req.body, (err, result) => {
if (err) return console.log(err)
res.redirect('/activities')
})
});
module.exports = router;