router.post('/orders/finish', function(req, res, next) {
var order_id = req.body.order_id;
var user_id = req.body.user_id;
var table_id = '';
var result = [];
mongo.connect(url, function(err, db) {
assert.equal(null, err);
db.collection('tables').update({id: table_id, status: true}, {$set: {status: false}}, function(err, result) {
assert.equal(null, err);
});
var cursorTables = db.collection('tables').find({status: false});
cursorTables.forEach(function(doc, err) {
assert.equal(null, err);
result.push(doc);
}, function() {
db.close();
res.send(JSON.stringify(result));
});
});
I'm updating table collection and try to get them, but I get old collection without updating. However in the next request its changed.
When you make your .find() call, your collection isn't done updating yet.
You can choose to call .find() in the callback of your .update() call, or you could also use promises or async/await depending on your version.
Another solution would be to use findAndModify with the new option:
Optional. When true, returns the modified document rather than the original. The findAndModify() method ignores the new option for remove operations. The default is false.
You should wait for the update to complete before calling find
db.collection('tables').update({id: table_id, status: true}, {$set: {status: false}}, function(err, result) {
assert.equal(null, err);
var cursorTables = db.collection('tables').find({status: false});
cursorTables.forEach(function(doc, err) {
assert.equal(null, err);
resultTables.push(doc);
}, function() {
db.close();
});
});
I recommend you use Async
router.post('/', function(req, res) {
var order_id = req.body.order_id;
var user_id = req.body.user_id;
var table_id = '';
mongo.connect(url, table_id, function(err, db) {
myFuntion(db, table_id, function(result) {
res.send(JSON.stringify(result)); // it should be what you need
})
})
});
function myFuntion(db, table_id, callback) {
var result = [];
async.waterfall([
function(callback) {
db.collection('tables').update({id: table_id, status: true}, {$set: {status: false}}, function(err, result) {
assert.equal(null, err);
callback(null);
});
}, function(callback) {
db.collection('tables').find({status: false}, function(err, docs) {
docs.forEach(function(doc) {
result.push(doc);
})
callback(null, result);
});
}
], function(err, result) {
callback(result);
})
}
Related
When ever I try to just use a simple find() for my mongodb it returns undefined.
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/local';
MongoClient.connect(url, function (err, db) {
db.collection('pokemon').find({ $search: { $text: 'Pikachu' } }).toArray(function(err, data){ console.log(data) })
});
EDIT:
Turns out I never created an index by putting
db.collection('pokemon').createIndex({Name: 'text'})
before all the code.
First of all, every time where you have:
function(err, data){ console.log(data) }
you should check errors:
function (err, data) {
if (err) {
console.log('Error:', err);
} else {
console.log('Data:', data);
}
}
Then you will probably see what's going on.
This is also true for the database connection itself - instead of:
MongoClient.connect(url, function (err, db) {
// use db here
});
you should handle errors:
MongoClient.connect(url, function (err, db) {
if (err) {
// handle errors
} else {
// use db here
}
});
If you don't handle errors then don't be surprised that you don't know why you don't get values.
I am currently trying to run a set of MySQL query's in order using async.js series control flow function. But I keep receiving the following error:
throw err; // Rethrow non-MySQL errors
^
TypeError: Cannot read property 'status' of undefined
I have tested the query's in seperate functions outside the async.series and they are fine and give me back the data, the only reason I can think for the error is due to the async nature it doesn't have the data at that time hence the error E.G when I log the rows I get:
[]
[]
[]
Below is the Async function:
function SQLuserDataAsync() {
connection.getConnection(function (err, connection) {
async.series([
function (callback) {
connection.query('SELECT status FROM users WHERE name= ?;',
[userval],
function (err, rows) {
if (rows[0]['status']) {
console.log("Account Status: " + accountval);
} else {
console.log(err);
}
callback(null, 'one');
});
},
function (callback) {
connection.query('SELECT account_type FROM settings_tbl WHERE id=(SELECT id FROM users WHERE name= ?);',
[userval],
function (err, rows) {
if (rows[0]['account_type']) {
var acctype = rows[0]['account_type'];
console.log("Account Type: " + acctype);
} else {
console.log(err);
}
callback(null, 'two');
});
},
function (callback) {
connection.query('SELECT type FROM settings_tbl WHERE id=(SELECT id FROM users WHERE name= ?);',
[userval],
function (err, rows) {
if (rows[0]['type']) {
var type = rows[0]['type'];
console.log("Type: " + type);
} else {
console.log(err);
}
callback(null, 'three');
});
}
]);
connection.release();
});
}
Any suggestions as the reason for the error or what am doing wrong here?
You've missed the main callback function to the async.series function.
function SQLuserDataAsync() {
connection.getConnection(function (err, connection) {
async.series([
function (callback) {
// YOUR CODE
},
function (callback) {
// YOUR CODE
},
function (callback) {
// YOUR CODE
}
], function(error, results) { // <--- this is the main callback
connection.release();
});
});
}
You should call connection.release() inside the main callback, otherwise, the MySQL connection will be released/terminated before the queries are executed (due to the asynchronous nature the code).
if there is a user with defined in userval name it will work.
But let's simplify our code:
function SQLuserDataAsync(userval) {
connection.getConnection(function (err, connection) {
async.waterfall([
// getting user
function (next) {
connection.query(
'SELECT * FROM users WHERE name = ? LIMIT 1',
[userval],
function (err, result) {
next(err, result[0]); // passing user to next function
});
},
// getting settings of user, maybe user_id (not id) in query below
function (user, next) {
connection.query(
'SELECT * FROM settings_tbl WHERE id = ? LIMIT 1',
[user.id],
function (err, result) {
next(err, user, result[0]);
});
},
// handling both user and settings
function (user, settings, next) {
console.log('User: ', user);
console.log('Settings: ', settings);
connection.release();
}
]);
});
}
SQLuserDataAsync('someone');
exports.save = function(req, res) {
connection.query('INSERT INTO student_details(name, course, units, grades, gwa) VALUES(?, ?, ?, ?, ?)',[req.body.name,req.body.course,req.body.units,req.body.grades,req.body.gwa], function(err, row) {
if(err) res.send('Error in query');
selectOne(row.insertId, function(newRow){
if(err) res.status(554).send('Error in query');
if(newRow == null){
res.send(552, {message: 'Student Details ('+row.insertId+') was not created.'});
} else{
res.status(200).send(newRow);
}
});
});
}
var selectOne = function(id, callback){
connection.query('SELECT * FROM student_details WHERE id=? LIMIT 1', [id], function(err, rows){
if(err) return err;
if(rows.length != 0){
callback(rows[0]);
}else{
callback(null);
}
});
}
I'm having an error performing the query above. It's saying this error:
Uncaught TypeError: Cannot read property 'insertId' of undefined.
I've been trying to figure this out for hours now, and my hunch is that it's somewhat related to asynchronous values but I can't figure out how to fix it.
UPDATE:
This is my test file:
var studentdb = require(__dirname + '/../studentdb'),
student = require(__dirname + '/../student'),
index = require(__dirname + '/../index'),
should = require('should-http'),
assert = require('assert'),
request = require('supertest');
describe('Student Details', function() {
var url = 'http://localhost:1337';
var randomName = student.getRandomName(10);
var insertedId = 0;
describe('insert()', function () {
it('should create a new student record', function (done) {
var input = {
nameLength: 10,
subjectsLength: 5,
course: 'CAS'
};
studentName = student.getRandomName(input.nameLength);
studentCourse = student.getRandomCourse(input.course);
studentUnits = student.getRandomUnits(input.subjectsLength);
studentGrades = student.getRandomGrades(input.subjectsLength);
studentGWA = student.computeGWA(studentUnits, studentGrades,input.subjectsLength);
var stringUnits = studentUnits.join();
var stringGrades = studentGrades.join();
var generatedStudent = {
'name': studentName,
'course': studentCourse,
'units': stringUnits,
'grades': stringGrades,
'gwa': studentGWA
}
request(url)
.post('/addStudent')
.send(generatedStudent)
.end(function(err, res) {
if (err) {
throw err;
}
res.should.have.status(200);
res.body.should.have.keys(['id', 'name', 'course','units', 'grades', 'gwa']);
done();
});
});
});
describe('save()', function() {
console.log(insertedId);
it('should generate a student record', function(done) {
request(url)
.get('/generateStudent')
.end(function(err, res) {
if(err) throw err;
res.should.have.status(200);
res.body.should.not.have.property('name', null);
res.body.should.not.have.property('course', null);
generatedStudent = res.body;
done();
});
});
it('should not have duplicate name', function(done) {
request(url)
.get('/getStudents')
.end(function(err, res) {
if(err) throw err;
res.body.forEach(function(iteration) {
assert.notEqual(iteration, generatedStudent.name);
});
done();
});
});
it("now adding to the database", function(done) {
request(url)
.post('/addStudent')
.send(generatedStudent)
.end(function(err, res) {
if(err) throw err;
res.body.should.have.status(200);
console.log(res.body.id);
res.body.should.have.keys(['id', 'name', 'course', 'units', 'grades', 'gwa']);
done();
});
});
});
});
----------SECOND UPDATE after following Zeeshan's code------------------
they keep on rejecting my edit in the comment section.
Again, I've tried your suggestion but still no cigar. I've also printed the "newRow" to show that the data is being retrieved properly, it's just that when I try the res.send function, it is being read as undefined therefore causing the error. Thank you for your patience!
Server Connected on port: 1337
Student Details
insert()
Database is connected ... nn
If error, I should not be printed
Value of row.insertId 34
{ id: 34,
name: 'H3tno72Osk',
course: 'BS Computer Science',
units: '4,1,2,4,2',
grades: '3.0,3.0,3.0,3.0,4.0',
gwa: 3 }
✓ should create a new student record (66ms)
save()
✓ should generate a student record
✓ should not have duplicate name
1) now adding to the database
3 passing (90ms)
1 failing
1) Student Details save() now adding to the database:
Uncaught AssertionError: expected Object { body: undefined, statusCode: undefined } to have property statusCode of 200 (got undefined)
at Assertion.fail (node_modules/should/lib/assertion.js:92:17)
at Assertion.Object.defineProperty.value [as status] (node_modules/should/lib/assertion.js:164:19)
at Test.<anonymous> (test/studentdb.js:86:27)
at Test.assert (node_modules/supertest/lib/test.js:156:6)
at assert (node_modules/supertest/lib/test.js:127:12)
at node_modules/supertest/lib/test.js:124:5
at Test.Request.callback (node_modules/supertest/node_modules/superagent/lib/node/index.js:691:12)
at IncomingMessage.<anonymous> (node_modules/supertest/node_modules/superagent/lib/node/index.js:922:12)
at _stream_readable.js:920:16
Modified a bit, Can you try this as well and update with results?
exports.save = function(req, res) {
connection.query('INSERT INTO student_details(name, course, units, grades, gwa) VALUES(?, ?, ?, ?, ?)',[req.body.name,req.body.course,req.body.units,req.body.grades,req.body.gwa], function(err, row) {
if(err) return res.send('Error in query');
console.log("If Errror I should not pe printed");
console.log("Value of row.insertId ", row.insertId);
selectOne(row.insertId, function(newRow, insertId){
if(err) res.status(554).send('Error in query');
if(newRow == null){
res.send(552, {message: 'Student Details ('+insertId+') was not created.'});
} else{
res.status(200).send(newRow);
}
});
});
}
var selectOne = function(id, callback){
connection.query('SELECT * FROM student_details WHERE id=? LIMIT 1', [id], function(err, rows){
if(err) return err;
if(rows.length != 0){
callback(rows[0], id);
}else{
callback(null, id);
}
});
}
So, I have managed to get the result that I wanted. I ended up comparing the id count from the insert() function, instead of the save() function.
describe('insert()', function () {
it('should create a new student record', function (done) {
var input = {
nameLength: 10,
subjectsLength: 5,
course: 'CAS'
};
studentName = student.getRandomName(input.nameLength);
studentCourse = student.getRandomCourse(input.course);
studentUnits = student.getRandomUnits(input.subjectsLength);
studentGrades = student.getRandomGrades(input.subjectsLength);
studentGWA = student.computeGWA(studentUnits, studentGrades, input.subjectsLength);
var stringUnits = studentUnits.join();
var stringGrades = studentGrades.join();
var generatedStudent = {
'name': studentName,
'course': studentCourse,
'units': stringUnits,
'grades': stringGrades,
'gwa': studentGWA
}
request(url)
.post('/addStudent')
.send(generatedStudent)
.end(function(err, res) {
if (err) {
throw err;
}
res.should.have.status(200);
insertedId = res.body.id;
res.body.should.have.keys(['id', 'name', 'course', 'units', 'grades', 'gwa']);
done();
});
});
});
You should exec return if got err. The simplest way to do this is if(err) return res.send('Error in query');.
i am very new to nodejs. I am using oracledb and want to make the queries in synchronous order. So once 1st query is executed then output of the query will be used in second query. i looked at async.waterfall and wrote below code. is it correct way to call function in synchronous way ? Thanks in Advance. it may be possible that 1st query takes more time than second.
var update = function(fnParam1, fnParam2){
oracledb.maxRows = 10000;
oracledb.getConnection(
{
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection)
{
if (err) { console.log(err.message); return; }
async.waterfall([
function(callback) {
connection.execute("select column1 from table1 where param1 =:nm",[fnParam1],
function(err, result)
{
if (err) { console.log(err); return; }
column1 = String(result.rows[0][0]);
});
callback(null, column1,connection);
},
function(column1, connection,callback) {
connection.execute("select count(*) from table2 where column1 = :par1 and column2= :par2",[column1,fnParam2],
function(err, result)
{
if (err) { console.log(err); return; }
var count = String(result.rows[0][0]);
console.log("count result:" + count)
});
callback(null, count);
}
],
function (err, result) {
console.log("Done" + result);
});
});
};
Just taking a quick look at the code, I noticed your "callback" invocations are not in the callback functions that are passed to execute. This means your going to the next step in your waterfall before you have the results from the execute method. Here's your code slightly modified to demonstrate what I mean. Also, don't forget to release your connection when you're done with it.
var update = function(fnParam1, fnParam2){
oracledb.maxRows = 10000;
oracledb.getConnection(
{
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection)
{
if (err) { console.log(err.message); return; }
async.waterfall([
function(callback) {
connection.execute("select column1 from table1 where param1 =:nm",[fnParam1],
function(err, result)
{
if (err) { console.log(err); return; }
column1 = String(result.rows[0][0]);
callback(null, column1, connection);
});
},
function(column1, connection, callback) {
connection.execute("select count(*) from table2 where column1 = :par1 and column2= :par2",
[column1,fnParam2],
function(err, result)
{
if (err) { console.log(err); return; }
var count = String(result.rows[0][0]);
console.log("count result:" + count);
callback(null, count);
});
}
],
function (err, result) {
console.log("Done" + result);
});
});
};
Pretty sure this is a quite noobish node.js/callback question but I can't seem to find the proper code to make it run.
This is how I invoke my node-mysql code:
var utils = require('../../config/database/utils');
exports.getResults = function(callback) {
var query = "SELECT * FROM my_table";
utils.exec(query, null, function(err, results){
if(err){
console.log(err);
callback(true);
return;
}
console.log(results);
callback(false, results);
});
};
Next is the utils file where I can't get the code work.
var pool = require('./connection');
module.exports = {
getDBConnection: function() {
pool.getConnection(function(err, connection){
if(err){
console.log(err);
return;
}
return connection;
});
},
endDBConnection: function(connection) {
connection.end(function (err) {
if(err) {
console.log(err);
callback(true);
return;
}
});
},
exec: function(query, data, callback) {
console.log(query);
this.getDBConnection(function(err, connection){
if(err){
console.log('error');
}
console.log(connection);
connection.query(query, data, function(err, results) {
if(err) {
callback(err);
}
callback(false, results);
});
this.endDBConnection(connection);
});
}
}
Code is getting OK the the exec part since the console.log(query) logs the query. But after that, the code's not running, console.log(connection); doesn't show a thing, and of course the connection.query is also not running.
I'm not sure why this is happening.
Returning a value inside a callback is meaningless. You need to pass in a callback that gets called with the value you want to return:
getDBConnection: function(callback) {
pool.getConnection(function(err, connection){
if(err){
console.log(err);
return callback(err);
}
callback(null, connection);
});
},
You should also use connection.release() instead of connection.end() since you are using a pool:
endDBConnection: function(connection) {
connection.release();
},
In exec(), you have the wrong this. It should instead be something like:
exec: function(query, data, callback) {
console.log(query);
var self = this;
this.getDBConnection(function(err, connection){
if(err){
console.log('error');
return callback(err);
}
console.log(connection);
connection.query(query, data, function(err, results) {
self.endDBConnection(connection);
if(err) {
return callback(err);
}
callback(null, results);
});
});
}