I made node.js app that includes some REST services. Those services connect to a database (for example Oracle or DB2) to execute some query.
Since I'm a beginner in node.js programming, I have a question about my case:
What's the right way to access to a database? Is it better to have one connection reference while the app is running and use the same connection instance when REST services are called?
I found some examples that includes database connection in a separate module and use that module in app, something like that:
db2.js:
var db2 = require('ibm_db');
var db2ConnSettings = "DRIVER={DB2};DATABASE=mydb;HOSTNAME=localhost;UID=db2test;PWD=db2test;PORT=50000;PROTOCOL=TCPIP";
var db2Conn = db2.open(db2ConnSettings, function(err, conn) {
if (err)
return console.log(err);
});
module.exports = db2Conn;
server.js:
var express = require('express');
var app = express();
var db2Connection = require('./db2.js');
app.get('/data', function(req, res) {
console.log(db2Connection );
// make some query
});
When this service is called, db2connection is undefined. How come? How should I retrieve a db2 connection from db2.js file?
As said by #Sirko:
db2.js
var db2 = require('ibm_db');
var db2ConnSettings = "DRIVER={DB2};DATABASE=mydb;HOSTNAME=localhost;UID=db2test;PWD=db2test;PORT=50000;PROTOCOL=TCPIP";
var err, conn;
var callbacks = [];
module.exports = function(callback) {
// db2 module is called
if (err || conn) {
// connection has already been established
// (results of db2.open have been stored)
// callback immediately
callback(err, conn);
}
else {
// connection has not been established
// store the callback for when db connects
callbacks.push(callback);
}
};
db2.open(db2ConnSettings, function(_err, _conn){
// db has connected
err = _err; conn = _conn; // store results
var next_callback;
// array.pop() removed the last item from the array
// and returns it. if no items are left, returns null.
// so this loops through all stored callbacks.
while(next_callback = callbacks.pop()) {
// the removed item is stored in next_callback
next_callback(err, conn); // send connection results to callback
}
// no more items in callbacks to trigger
});
server.js
var express = require('express');
var app = express();
var db2Connection = require('./db2.js')(function(err, conn) {
// triggered if the connection has already been established
// or as soon as it HAS been established
app.get('/data', function(req, res) {
console.log(conn);
// ...
});
});
For Oracle with node-oracledb it's simple to create and use a connection pool. Your app would just get a free connection from the pool whenever it handles an HTTP REST request. Look at webapp.js and webapppromises.js in the examples. Node-oracledb has a 'connection pool queue' (see doc) which handles connection load spikes. It also has a 'connection pool cache' (also see the doc) which makes it easy to access a pool created in a different module.
Related
I'm trying to make a simple task.
In the first place, on client side, i'm sending data to server and then i insert these data into my mongodb database.
Then i try to get count of clients from my database.
var express = require('express');
var MONGO_URL = "mongodb://localhost:27017/mydatabase";
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
mongo = require('mongodb').MongoClient,
fs = require('fs');
var countUserSuscribed =0;
//here i insert data
/* Connection events */
io.on('connection', function (client) {
console.log("User connected");
client.on('InsertNewUser', function (newUser) {
console.log("we ar in InsertNewUser event");
//////////////////////////////////////////////////////////
mongo.connect(MONGO_URL, function (err, db) {
console.log("we are connected to mongodb");
var Users = db.collection('User');
console.log("on crée la collection et on fait l'ajout");
Users.insert({ player: myP }, function (err, o) {
if (err) { console.warn(err.message); }
else { console.log("user inserted into db: user"); }
});
});
})
});
//GET COUNT USER
console.log("here we get count user");
mongo.connect(MONGO_URL, function (err, db) {
countUserSuscribed = Users.count();
console.log("we got " + countUserSuscribed + " user in mongoDB");
});
With this code i can create collections and insert documents but the count function doesn't work and i didn't find much explanations on npm documentation.
Is it possible to use others mongodb functions than insert and collection with socket.io-mongodb ?
If it is, can someone give an example or explain me how to use it?
The count function works but is async function and takes a callback.
here's the fix:
countUserSuscribed = Users.count(function (err,c) { console.log(c) });
https://www.npmjs.com/package/mongodb-autoincrement consider using that. It keeps a track of all inserted document. Plus it has a handy feature to get the next count. Example let's say you inserted two records. If you call next count it will show 3. There fore to get the total documents inserted call get next count - 1. Make sense?
Sorry here is the correct one. https://www.npmjs.com/package/mongoose-auto-increment
I am creating the nodejs application which uses the mongodb.
I am connecting to mongodb only once. I want to use db in all other api's so as to achieve the connection pooling.
I have following code for mongodb connectivity:
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var db;
var mongoUrl = "mongodb://localhost:27017/testDB";
/**
* Connects to the MongoDB Database with the provided URL
*/
exports.connect = function(callback){
if(!db){
MongoClient.connect(mongoUrl, function(err, _db){
if (err) { throw new Error('Could not connect: '+err); }
db = _db;
console.log(db);
connected = true;
console.log(connected +" is connected?");
callback(db);
});
}else{
console.log("Not connected tis time as I am already connected");
callback(db);
}
};
exports.db = db;
I am calling connect only once when server starts from app.js. Whenever other api such as signin, register get called, they should simply use db that is exported.
So my api calls will something like(please ignore the syntax error in api call :D):
var mongo = require('./mongo');
collection = mongo.db.collection("testCollection");
// Here mongo.db id undefined
collection.findOne({"name":"John"}, function(err, result){
// Do your stuff with result here
});
From other stackoverflow posts, I tried something like in mongo.js as
module.export{
db: db,
connect : function(callback){
//function code goes here
}
}
But still I am getting the undefined for mongo.db
How would I access mongo.db in my other files?
Thanks
The reason this happens is, because connect overwrites db in the module. The exports.db=db; is not executed after calling your connect function, but on execution of the module import.
So, when you call connect, db is set to another variable, but that is not exposed outside.
Didn't do much JS lately, but this should do it:
module.exports = new mongobj();
function mongobj() {
this.db = null;
this.connect = function(callback) { /* your connect code set mongobj.db */
this.db = /* new value */ ;
}
}
When you import the module, you get the object. Accessing the objects db property will always expose the latest db value set by the connect function of the module.
var mongo = require('yourmodule');
// mongo.db is null
mongo.connect(some callback);
// mongo.db is set
This connection add in main script file...
var mongodb = require('mongodb');
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var mongoUrl = "mongodb://localhost:27017/testDB";
ObjectId = module.exports = require("mongojs").ObjectId;
MongoClient.connect(mongoUrl, function(err, database){
if(err){
console.log("mongodb error >>"+err);
} else {
db = module.exports = database;
}});
db.collection('game_users').findOne({_id:ObjectId("123456789")},function(err, data) {});
define an object:
var db = {__db: undefined}
and then:
exports.db = db
const db = require('./mongo').db.__db
I have been creating a website with Mean stack and I stuck at some point. I have a mongo db database and I am currently getting each file from database (to show them on Main page) with my Rest Api which is build with Express.
Server.js
var express = require('express');
var app = express();
var mongojs = require('mongojs');
var db = mongojs('mongodb://username...', ['myApp']);
var bodyParser = require('body-parser');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());
app.get('/myApp', function (req, res) {
db.myApp.find(function (err, docs) {
console.log(docs);
res.json(docs);
});
});
app.get('/myApp/:id', function (req, res) {
var id = req.params.id;
console.log(id);
db.myApp.findOne({_id: mongojs.ObjectId(id)}, function (err, doc) {
res.json(doc);
})
});
app.listen(3001);
console.log('Server running on port 3001');
There is 2 get method and I can understand that because they have different parameters. So when I call them from controllers, there is no problem because if I provide id, it will call the second get method. But for example I want to use something like this in my website;
app.get('/myApp', function (req, res) {
db.myApp.find({}).limit(2).skip(0, function(err, docs) {
console.log(docs);
res.json(docs);
});
});
This get method have no parameter like the first get method in server.js but they do different jobs. This is limiting my search with 2 file. How can I use different get methods like this in my Mean Stack application?
This is my code for calling get method from my main controller. How can I make sure to call specific get method? Thanks..
$http.get('/myApp').success(function(response) { .. });
What you want is not possible. Somehow you need to distinguish between your 2 intentions, either by giving the endpoints different names (like you already suggest in your comment) or by providing for example a query parameter so you could do a call like:
$http.get('/myApp?limit=2').success(function(response) { .. });
When limit is omitted, you could return all results.
Something like:
app.get('/myApp', function (req, res) {
var limit = req.query.limit;
if (limit === undefined) {
// Return everything
} else {
// make sure limit is some valid number
// ... and do a mongo query limited to this number
}
});
I am trying to create a basic messaging system using express/nodejs. While I am able to emit messages to all users successfully. I need for users to be able to message each other in a 1-to-1 private manner.
What I am trying to do below is simple. When a user logs in, once the session has been validated, store the user object in the clients array and make this array accessible in the view -- that's it!
The intention is that this array will to grow on the server as users log in and I'll need to make it accessibly in the view, so I can generate a list of online users that are available for chat.
I have tried several different approaches, the approach below results in an empty array in the view.
My goal is to simply store online users in an array on the server as they log in and have that array accessible in the view.
I appreciate any suggestions.
index.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mysql = require('mysql');
var session = require('client-sessions');
var server = require('http').createServer( app );
var io = require('socket.io').listen( server );
var clients = [];
app.locals.delimiters = '<% %>';
app.get('/', function(req, res){
if(req.session && req.session.user.username){
mysql.query("SELECT * FROM users WHERE username = ? AND pass = ? LIMIT 1", [req.session.user.username, req.session.user.pass], function(error, results, fields){
if(results.length === 0){
req.session.reset();
res.redirect('/login');
}else{
res.locals.user = results[0];
io.sockets.on('connection', function(socket){
clients.push({user : res.locals.user, socket : socket});
});
res.render('index');
}
});
}else{
res.redirect('/login');
}
});
server.listen( 3331 ); //chat port
io.sockets.on('connection', function(socket){
//load all users
socket.on('load users', function(){
io.emit('load users', {clients : clients});
});
socket.on('error', function(err){
console.error(err.stack);
});
});
module.exports = app;
index.hjs
<div class="messenger-user" ng-repeat="n in clients">
<div class="avatar-icon glyphicon glyphicon-user">
</div>
<div class="user-meta">
{{n.user.firstname}} {{n.user.lastname}}
</div>
</div>
index.hjs JavaScript
socket.emit('load users', function(clients){
$scope.clients = clients;
$scope.$apply();
});
Makes perfect sense. It sends an empty array because you send it before populating it.
Currently :
1) A MySQL query is launched to retrieve and populate the users array.
2) Meanwhile, a socket on 'connection' event is triggered (line 24), that emits the users array, which is currently empty.
3) Your MySQL query ends (line 3) and gets back with the data you want.
4) Inside the callback function, you set another listener for io.sockets.on('connection'). It's too late, because you already set one, and the connection event already happened. So you have two listeners for the same event, and the second one never triggers.
What you should do is wait for the SQL query to end, then populate your array and emit it to the client.
Edit 2 : Don't use both HTTP connection and socket for authentication. You're trying to store a user object from a HTTP request, together with a socket that is unrelated to the HTTP request. Do everything with the sockets :
var clients = [];
io.sockets.on('connection', function(socket){
socket.on('credentials', function(data){ // data == { "username":"John" , "password":"123456" }
login(data, socket); // sending credentials and socket to the login function, so both are defined there.
})
socket.on('error', function(err){
console.error(err.stack);
});
});
function login(data, socket){
mysql.query("SELECT * FROM users WHERE username='"+data.username+"' AND pass='"+data.password+"' LIMIT 1", [req.session.user.username, req.session.user.pass], function(error, results, fields){
if(!results.length){
req.session.reset();
res.redirect('/login');
}else{
clients.push({user : results[0], socket : socket}); // Both defined!
io.emit('load users', {clients : clients});
res.render('index');
}
});
}
server.listen( 3331 ); //chat port
I am using Express, node.js and socket.io. What I would like to implement is a system in which everytime a user connects to the page (upon 'connection' event), an SQL request is performed so the results are emitted to the user by trigerring the event 'get_recipes'. However, after refreshing the page several times, the event 'get recipes' is not triggered anymore... Can someone tell me what is wrong with my code (do I need to log out from the database ? If so, how ?) ? Thanks a lot !
app.js :
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var pg = require('pg').native;
var db_URL = "tcp://user1:default#localhost/dbtest";
...
io.sockets.on('connection', function (socket) {
pg.connect(db_URL, function(err, client) {
client.query("SELECT * FROM Recipes", function(err, results) {
socket.emit('get_recipes', results);
});
});
});