Getting variable outside of query block in Nodejs with sqlLite - javascript

I want to store all the rows from table to array(arr), I need to get the stored array outside of the defined query section. Is there a way I can get all the rows outside db.each such that I can manipulate them further.
var arr=[];
db.each("SELECT * FROM login", function(err, row) {
var title=row.title;
var context=row.context;
var newItem = {
'user': user,
'pwd': pwd
};
arr.push(newItem);
});
console.log(arr); //Outputs []

Because db.each is an asynchronous function, you need to use another function as a callback, like:
var arr=[];
db.each("SELECT * FROM login", function(err, row) {
var title=row.title;
var context=row.context;
var newItem = {
'user': user,
'pwd': pwd
};
arr.push(newItem);
}, function(){
console.log(arr)
});
Reference: https://github.com/mapbox/node-sqlite3/wiki/API#databaseeachsql-param--callback-complete

Related

Global scope of last insertId using node.js + mysql

I am calling function in order to insert some values into a database table using mysql module of node.js. The function is called inside a for loop and I can get the last insertId of each INSERT query inside the function.
MY PURPOSE
I want to store these id's to an array in to order to use them later in my code but I cannot do that.
- FUNCTION CALL
for(var i=0;i<some_number;i++){
if (<something is true>){
var lastid = [];
//Function calling
function_a(x, y, z, w, function(error, result) {
if(!error){
lastid.push(result.insertId);
}
//To Do
else{}
});
}
}
- FUNCTION
function function_a(a, b, c, d, callback){
//Connection to the DB
const con = mysql.createConnection({
host: 'host',
user: 'user',
password: 'password',
database: 'database'
});
//DB query
var query = "INSERT INTO my_table (column1, column1, column1, column1) VALUES ('"+a+"', '"+b+"', '"+c+"', '"+d+"')";
con.query(query, (err, rows) => {
var e = rows.insertId;
return callback(err, e);
});
con.end();
}
The problem is that I cannot use the id's outside the function.
Any idea how can I do that?Is this about variable scope?
Several problems here, and yes, they are partly about variable scope.
Put var lastid = []; before the for loop, so you can use it after the loop. However, as you have callback mechanism inside the loop, you must wait for the whole loop to finish (all callbacks called from 0 to some_number-1, in order to have the right values in lastid array. It's a messy thing with callbacks, but you can do it with them or with promises. You can Google for callback handling in for loops.
The function function_a is a asynchronous function. In your case you can use async module to do this task:
var taskIds = Array.apply(null, {length: some_number}).map(Number.call, Number);
var lastid = [];
async.eachLimit(taskIds, 32, function (taskId, done) {
if (<something is true>) {
function_a(x, y, z, w, function(error, result) {
if(!error){
lastid.push(result.insertId);
}
//To Do
else{}
done()
});
} else {
done()
}
}, function () {
// Do some thing with lastid
console.log(lastid);
});

nodeJS create dynamic array and use as response

Hi i am creating an empty array then populating it with data from a mongo query using a forEach Loop.
i have been attempting this now for 4 days and nothing i seem to do is working i know im close but being a newbie to javascript and MEAN stack i just cant figure it out.
i have attached the code with comments on everything i am trying to do.
please any help would be awesome..
var mongoose = require('mongoose'),
User = require('../../models/UserModel'),
async = require('async');
module.exports.getfollowing = function(req, res){
//grab the Users ID from the body
var thefollower = req.body.follower;
//create empty array that i want to populate with the followee's ID and Avatar url
var obj = [];
//query mongo for the user
User.findOne({ _id: thefollower }, function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
//grab the following element of the users mongo schema -- should return all the followee's ID's -- tested works
var following = user.following;
//iritate throught all the followee's
async.forEach(following, function(item, callback) {
//current followee
var user = item;
//query mongo for the followee
User.findOne({_id: user}, function(err, followee, callback){
//get followee's ID and Avatar url
var id = followee._id;
var avatar = followee.avatar;
//add the followee's ID and Avatar url to the obj array
obj.push({
id: id,
avatar: avatar
});
});
//see if this worked - returns empty
console.log(obj);
callback();
}, function(err) {
//see if this worked - returns empty
console.log(obj);
//respond to the client - returns empty
res.json(obj);
});
}
});
};
You need to move your callback(); that is at the end of your async.forEach() callback to inside the User.findOne({_id: user}, ...) callback (right after you call obj.push()) because that is when you are actually done with item. With your current code you are telling the async module immediately that you are done with item, before your mongo query has a chance to complete.
mscdex
Was spot on his answer solved my issue for future help to others here is the code
var mongoose = require('mongoose'),
User = require('../../models/UserModel'),
async = require('async');
module.exports.getfollowing = function(req, res){
//grab the Users ID from the body
var thefollower = req.body.follower;
//create empty array that i want to populate with the followee's ID and Avatar url
var obj = [];
//query mongo for the user
User.findOne({ _id: thefollower }, function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
//grab the following element of the users mongo schema -- should return all the followee's ID's -- tested works
var following = user.following;
//iritate throught all the followee's
async.forEach(following, function(item, callback) {
//current followee
var user = item;
//query mongo for the followee
User.findOne({_id: user}, function(err, followee){
//get followee's ID and Avatar url
var id = followee._id;
var avatar = followee.avatar;
//add the followee's ID and Avatar url to the obj array
obj.push({
id: id,
avatar: avatar
});
//see if this worked - returns empty
console.log(obj);
callback();
});
}, function(err) {
//see if this worked - returns empty
console.log(obj);
//respond to the client - returns empty
res.json(obj);
});
}
});
};

Inserting more than one record with Node.js and Tedious

I have an array of customer objects, that I wish to insert to the SQL database.
The customer objects are retrieved from the req data.
I am using Tedious for the request, and Tedious Connectionpool in order to have multiple connections at the same time.
When looping over the objects i am getting an error when trying to insert, the error being
{ [RequestError: Violation of PRIMARY KEY constraint `'PK__Customer__A4AE64D873A5400C'. Cannot insert duplicate key in object 'dbo.Customer'. The duplicate key value is (2).]`
Note that I only have 3 object being send in the req at this time. It looks to me that it is only the last object that are being handled and inserted. But since I am new to using tedious with Node.js i cant spot my mistake. Any suggestions ?
router.post('/',jsonParser, function(req, res) {
var customers = req.body.customers;
var companies = req.body.companies;
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
var config = {
userName: '*************',
password: '*************',
server: '***********.database.windows.net',
// When you connect to Azure SQL Database, you need these next options.
options: {encrypt: true, database: '*******'}
};
var poolConfig = {
min: 1,
max: 3,
log: true
};
var pool = new ConnectionPool(poolConfig, config);
for (var i = 0; i < customers.length; i++) {
console.log('Inserting '+customers[i].firstname);
var firstname = customers[i].firstname;
var count = i;
pool.acquire(function (err, connection) {
if (err)
console.error(err);
//use the connection as normal
var request = new Request("INSERT INTO dbo.Customer" +
" (Firstname,CustomerId)" +
"VALUES" +
" (#Firstname,#CustomerId);", function (err, rowCount) {
if (err)
console.error(err);
console.log('rowCount: ' + rowCount);
//release the connection back to the pool when finished
connection.release();
});
request.addParameter('Firstname', TYPES.VarChar,firstname);
request.addParameter('CustomerId', TYPES.Int, count);
request.on('row', function (columns) {
console.log('value: ' + columns[0].value);
});
connection.execSql(request);
});
pool.on('error', function (err) {
console.error(err);
});
}
});
The scope of your variables count and firstName are global. By the time the pool.acquire( function get's executed the for loop has completed and it is inserting the last customer twice. One possible solution would be to put an anonymous function inside the for loop e.g. (it doesn't have to be anonymous though)
for (var i = 0; i < customers.length; i++) {
(function(count, firstName) {
...do insert here...
}(i, customers[i].firstname));
}

Add sqlite query result to angularjs $scope

I have this sqlite query in a angularjs app.
$scope.testArr = [];
$scope.testFunk = function(){
var db = window.openDatabase("test", "1.0", "Test DB", 1000000);
db.transaction(function(tx){
tx.executeSql('SELECT * FROM EVENTS',
[],
//Callback function with transaction and
//results objects
function(tx, results){
//Count the results rows
var rowsCount = results.rows.length;
//Loop the rows
for (var i = 0; i < rowsCount; i++){
//Build a results string, notice the
//column names are called
$scope.testArr.push({
id: results.rows.item(i).eventId,
nameSel: results.rows.item(i).eventNameSel,
name: results.rows.item(i).eventName,
eventDesc: results.rows.item(i).eventDesc,
eventUrl: results.rows.item(i).eventUrl,
time: results.rows.item(i).eventTime
})
}
console.log($scope.testArr);
},
errorHandler);
});
}
//
The console.log returns the right objects, but If I do a console.log outside of the db.transaction function it returns empty. The problem is that I want to call the $scope.testFunk() function and return the result from the query to a variable which I then can process further, like:
var result = $scope.testFunk();
console.log(result);
// prints results from query.
I suggest you to use a service.
The reason it's not working now is because when you trying to print the results, it's still not populated. you can add $watch over results and work with it when it's populated.
$scope.testFunk(); // modify $scope.results within the function
$scope.$watch('results', function(resultsNewVal, resultsOldVal) {
console.log(resultsNewVal);
}

update mongodb with node.js using a variable in $set

I am making a voting system, the voting is done with a link. In my index.js I get the required values and put them in variables. The "type" variable stands for the field in my mongodb wich needs to be updated, I have put it in a variable because it depends on which link is clicked.
Now in the $set function they require the db field and a new value, for both I use variables but my "type" variable doesn't work. And when I go to my mongodb there is a new table created called "type". How can this be solved?
router.get('/vote/:Id/:Value/:Type', function(req, res) {
var db = req.db;
var id = req.params.Id;
var type = req.params.Type;
var value = parseInt(req.params.Value);
var newValue = value + 1;
var collection = db.get('games');
collection.update(
{"_id" : id},
{$set: {type: newValue}}
, function (err, doc) {
if (err) {
res.send("There was a problem");
}
else {
res.location("../../../admin");
res.redirect("../../../admin");
}
});
});
In javascript you cannot use variables as property names in object literals, and that's what you're trying to do.
Try it:
var a = 'someProperty';
var o = {a: 'somePropertyValue'};
console.log(o);
will print { a: 'somePropertyValue' } not {someProperty:'somePropertyValue}.
If javascript permitted referencing variables in property names in object literal notation it would have to get rid of unquoted names as those would create ambiguity.
Should a be used as the value of the property or should it be the value of the variable a?
Try creating the update object literal with an object crated beforehand without the usage of object literal notation, so your code looks something like this:
router.get('/vote/:Id/:Value/:Type', function(req, res) {
var db = req.db;
var id = req.params.Id;
var type = req.params.Type;
var value = parseInt(req.params.Value);
var newValue = value + 1;
var collection = db.get('games');
//We create the $set property/value pair using property assignment, not the object literal
var updateVal = {};
updateVal[type] = newValue;
collection.update(
{"_id" : id},
{$set: updateVal} //use it here
, function (err, doc) {
if (err) {
res.send("There was a problem");
}
else {
res.location("../../../admin");
res.redirect("../../../admin");
}
}
);
});
Even better, construct the whole $set operation beforehand.

Categories