私は読んで読んでいますが、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;
今、私はこれが間違っているという恐ろしい感覚を持っているので、このアプローチには明らかな問題がありますか、もしそうならそれを改善する方法はありますか?
Mongoに接続し、mongo dbインスタンスを返す機能を備えたmongoUtil.js
モジュールを作成できます。
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()
のインスタンスが1つだけになるためです。常に同じインスタンスを返します。
コードはテストされていません。
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: '[email protected]',
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を使用している場合、 express-mongo-db モジュールを使用して、リクエストオブジェクトで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'));
routes/users.js
app.get('/', function (req, res, next) {
req.db // => Db object
});
約束として接続を初期化します。
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
})
})
go-olegは基本的に正しいですが、最近では(おそらく)「mongodb」自体を使用したくないので、フレームワークを使用してください。
たとえば、マングースは最も一般的なものの1つです。これが最初のserver.js
ファイルにあるものです:
const mongoose = require('mongoose');
const options = {server: {socketOptions: {keepAlive: 1}}};
mongoose.connect(config.db, options);
これが、セットアップに必要なものすべてです。これをコードのどこでも使用します
const mongoose = require('mongoose');
そして、mongoose.connect
で設定したインスタンスを取得します
受け入れられた答えに基づいたテスト済みのソリューション:
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;
構成オブジェクトを所定の場所で受け入れるためにこれを微調整する方法は多数ありますが、全体的には、最新の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;
}
dbconnection.jsのようなdbconnectionファイルを作成できます
const MongoClient = require('mongodb').MongoClient
const mongo_url = process.env.MONGO_URL;
module.exports = {
connect: async function(callback) {
var connection;
await new Promise((resolve, reject) => {
MongoClient.connect(mongo_url, {
useNewUrlParser: true
}, (err, database) => {
if (err)
reject();
else {
connection = database;
resolve();
}
});
});
return connection;
}
};
そして、あなたのアプリでこのファイルを次のように使用します
var connection = require('../dbconnection');
非同期関数内でこのように使用します
db = await connection.connect();
これがうまくいくことを願って
アプリケーションでmongooseを使用することを選択した場合、次のスニペットを使用してapp.jsファイルを編集します
app.js
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/Your_Data_Base_Name', {useNewUrlParser:true})
.then((res) => {
console.log(' ########### Connected to mongDB ###########');
})
.catch((err) => {
console.log('Error in connecting to mongoDb' + err);
});`
次のステップ:アプリケーションのモデルを定義するには、それらを必要とし、たとえば、CRUD操作を直接実行します
blogSchema.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const blogSchema = new Schema({
_id : mongoose.Schema.Types.ObjectId,
title : {
type : 'String',
unique : true,
required : true
},
description : String,
comments : [{type : mongoose.Schema.Types.ObjectId, ref: 'Comment'}]
});
module.exports = mongoose.model('Blog', blogSchema);
使用法createBlog.js
const Blog = require('../models/blogSchema');
exports.createBlog = (req, res, next) => {
const blog = new Blog({
_id : new mongoose.Types.ObjectId,
title : req.body.title,
description : req.body.description,
});
blog.save((err, blog) => {
if(err){
console.log('Server Error save fun failed');
res.status(500).json({
msg : "Error occured on server side",
err : err
})
}else{
//do something....
}
Uは常にmogoDBに接続する必要はありません....
これには少し遅れましたが、ソリューションも追加します。ここでの答えと比べると、はるかに新しいアプローチです。
とにかく、MongoDBバージョン4.0およびNode.js 3.0(またはそれ以降のバージョン)を使用している場合、MongoClient
の- isConnected()
関数を使用できます。
const MongoClient = require('mongodb').MongoClient;
const uri = "<your connection url>";
const client = new MongoClient(uri, { useNewUrlParser: true });
if (client.isConnected()) {
execute();
} else {
client.connect().then(function () {
execute();
});
}
function execute() {
// Do anything here
// Ex: client.db("mydb").collection("mycol");
}
これは私にとってはうまくいきました。それが役に立てば幸い。
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/';
var Pro1;
module.exports = {
DBConnection:async function()
{
Pro1 = new Promise(async function(resolve,reject){
MongoClient.connect(url, { useNewUrlParser: true },function(err, db) {
if (err) throw err;
resolve(db);
});
});
},
getDB:async function(Blockchain , Context)
{
bc = Blockchain;
contx = Context;
Pro1.then(function(_db)
{
var dbo = _db.db('dbname');
dbo.collection('collectionname').find().limit(1).skip(0).toArray(function(err,result) {
if (err) throw err;
console.log(result);
});
});
},
closeDB:async function()
{
Pro1.then(function(_db){
_db.close();
});
}
};