Connect existing MySql table with Strongloop - mysql

I am trying to create an REST API which should connect to an existing table in mysql database and return the data with respective to the parameter we send.
Actually nodejs and strongloop is new to me, this is first time am working with them. I have followed their docs and created a table in mysql my running a file like below
I have followed the commands to create model, properties etc from the below github docs
https://github.com/strongloop/loopback-example-database
create-test-data.js
var server = require('./server');
var dataSource = server.dataSources.accountDB;
var Account = server.models.account;
var accounts = [
{ email: 'foo#bar.com',
created: new Date(),
modified: new Date()
}, {
email: 'bar#bar.com',
created: new Date(),
modified: new Date()
} ];
var count = accounts.length;
dataSource.automigrate('account', function(er) {
if (er) throw er;
accounts.forEach(function(account) {
Account.create(account, function(er, result) {
if (er) return;
console.log('Record created:', result);
count--;
if(count === 0) {
console.log('done');
dataSource.disconnect();
}
});
});
});
This automatically creating table and records in my database, I don't want this.
Actually I already have a different table, which I want to connect with strongloop.
I am completely clueless, any help would be appreciated.

I found this trying to do the same thing. I fixed it so it would end gracefully. Works great for me.
Original: https://gist.github.com/serkanserttop/64fc2d4465fb154066db#file-discover-js
var path = require('path');
var app = require(path.resolve(__dirname, '../server'));
var fs = require('fs');
var loopback = require('loopback');
var app_dir = './';
require('node-babel')();
var dataSource = app.dataSources.accountDs;
var db = 'myDB',
owner = 'root';
function capitaliseFirstLetter(string) {
return string.charAt(0)
.toUpperCase() + string.slice(1);
}
function jsFileString(model_name) {
return '' + 'module.exports = function(' + capitaliseFirstLetter(model_name) + ') {\n' + '\t\n' + '};';
}
function autoGenerateModelFiles() {
dataSource.discoverModelDefinitions({
schema: db
}, function(err, models) {
var count = models.length;
console.log(models.length);
models.forEach(function(model) {
dataSource.discoverSchema(model.name, {
associations: true
}, function(err, schema) {
if (schema.options.mysql.schema !== db) {
console.log('options.mysql.schema !== db', schema);
}
fs.writeFile(app_dir + 'common/models/' + model.name + '.json', JSON.stringify(
schema, null, ' '), function(err) {
if (err) throw err;
console.log('Saved ' + model.name);
});
fs.writeFile(app_dir + 'common/models/' + model.name + '.js', jsFileString(
model.name), function(err) {
if (err) throw err;
console.log('Created ' + model.name + '.json file');
});
count = count - 1;
if (len === 0) {
console.log("DONE!", count);
dataSource.disconnect();
return;
}
});
});
});
}

What you actually need is to discover model from database. There is a documentation available on a strongloop page.
http://docs.strongloop.com/display/public/LB/Discovering+models+from+relational+databases;jsessionid=1FC0E473B7F589F4F1EFC0F25D269E3E
http://docs.strongloop.com/display/public/LB/Database+discovery+API
Here is a working example:
var ds = app.dataSources.accountDB;
ds.discoverModelDefinitions(function (err, models) {
models.forEach(function (model) {
ds.discoverSchema( model.name, function (err, schema){
console.log(schema);
});
});
});
Put this code somewhere inside server.js (i.e. inside boot method). I assume that you have setup datasource correctly and also have loppback mysql connector installed.This will loop through all tables and "schema" will contain model definition discovered from database.

You can use slc arc to generate the models based on your MySQL tables, after that you should be able to use the API to perform the basic CRUD operations. In the following link you can find more information about it:
https://strongloop.com/node-js/arc/

Related

Aws JSON Lambda function, 'date-holiday' package

I am building an AWS Lambda function that emails the S3 location of call recordings to a mailbox if the office is out of hours. I can get it to send emails if any call is made but when I enter the conditions I fall down. I want the function to only operate on holidays and outside office hours(Christmas, bank holiday.....). I haven't tried weekends yet but I know how to go about doing that. I want to use the 'date-holidays' package but I am having trouble getting it to work. I can get the emails to send if it is not between 9 & 5 but I cannot get them to send if it is say Christmas day.
Or if there is an easier way, please suggest
var aws = require('aws-sdk');
var ses = new aws.SES({
region: 'us-west-2'
});
var time = new Date().getHours();
var td = new Date().getDate();
const s3 = new aws.S3({
apiVersion: '2006-03-01'
});
if (time > 17 || time < 9){
if (td == hd){
exports.handler = function(event, context, callback) {
console.log("Incoming: ", event);
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
const now = new Date();
const news = `Event took place in https://s3.console.aws.amazon.com/s3/object/${bucket}/${key}`;
const params = {
Bucket: bucket,
Key: key,
};
var eParams = {
Destination: {
ToAddresses: ["***********.com"]
},
Message: {
Body: {
Text: {
Data: `${news}`
}
},
Subject: {
Data: `Voicemail notification for ${now}`
}
},
Source: "*************.com"
};
console.log('===SENDING EMAIL===');
var email = ses.sendEmail(eParams, function(err, data) {
if (err) console.log(err);
else {
console.log("===EMAIL SENT===");
// console.log(data);
console.log("EMAIL CODE END");
console.log('EMAIL: ', email);
context.succeed(event);
}
});
}
}
};
I'm not sure what trouble you have it with 'date-holidays', you could try uploading node_modules folder also with Lambda and test (there is a data/holidays.json file)
var Holidays = require('date-holidays')
hd = new Holidays('US', 'la', 'no')
if(hd.isHoliday(--now--)) {
}

Loopback unable to create and do operations on related models in model JS file

Unable to create relation in model.js file while through model.json file, it's working fine. I want to update booking table field on any updation in bidding table but my relation is not working in model.js file.
Bidding.belongsTo(Booking, {foreignKey: 'bookingId'});
^
ReferenceError: Booking is not defined
{
"error": {
"statusCode": 500,
"name": "TypeError",
"message": "Bidding.booking is not a function",
"stack": "TypeError: Bidding.booking is not a function\n.."
}
}
'use strict';
//var loopback = require('loopback');
//var boot = require('loopback-boot');
//var app = module.exports = loopback();
module.exports = function(Bidding) {
// var app = require('../../server/server');
// var Booking = app.models.Booking;
//Bidding.belongsTo(Myuser, {foreignKey: 'driver_id'});
Bidding.belongsTo(Booking, {foreignKey: 'bookingId'});
Bidding.observe('before save', function beforeSave(ctx, next) {
if (ctx.instance) {
//on create
ctx.instance.created = new Date();
ctx.instance.modified = new Date();
} else {
// on edit
// ctx.instance.lastUpdated = new Date();
console.log('updatesdd');
//Bidding.Booking.upsertWithWhere({id: ctx.instance.id},{ 'username': username}, function(err, results) {});
Bidding.booking(function(err, booking) {
console.log(ctx.booking);
});
}
next();
});
Bidding.observe('loaded', function beforeaccess(ctx, next) {
console.log(ctx.data);
next();
});
};
By following way you can perform the operations on your relates tables. I go through inbuilt user.js file where they have relation with AccessToken table and find the following solution for my problem.
Query which load you related table -
Here "booking" model has belongs to relation define in bidding.json
var booking = ctx.Model.relations.booking.modelTo;
Update Query call through StrongLoop API Explorer:
http://0.0.0.0/api/Biddings/update?where=%7B%22id%22%3A%2211%22%2C%22bookingId%22%3A6%7D
Where: {"id":"11","bookingId":6}
data: {"bid_status":"Accept"}
Bidding.observe('before save', function beforeSave(ctx, next) {
if (ctx.instance) {
//on create
ctx.instance.created = new Date();
ctx.instance.modified = new Date();
} else {
//on update
if(ctx.data.bid_status == "Accept");
{
if (ctx.where && ctx.where.bookingId && ctx.where.id) {
var bookingId = ctx.where.bookingId;
var booking = ctx.Model.relations.booking.modelTo;
booking.upsertWithWhere({id: bookingId},{ 'booking_status': 'Confirmed'}, function(err, results) {});
}
}
}
next();
});

NodeJS MySQL Query in .forEach() seems to not execute / execute only once

I am trying to write a little script that reads an xml-file and then imports the data I fetch into a MySQL-Database. The fetching works fine, but the inserting is a problem. I've worked with the .forEach to stay asnyc which helped me a lot and worked fine until I needed to insert the Data. When I tried to execute the "INSERT"-Query outside of the 'Loops' everything works fine, but as soon as I try to execute it inside of one it just inserts everything once and then stops. Also the console.log() message inside the connection.query() doesn't get executed, even though no error gets thrown.
This is my code:
console.log("Running import!");
//Import necessary modules
var fs = require("fs");
var config = require("./config");
var mysql = require("mysql");
var path = require("path");
var xml2js = require("xml2js");
var parser = new xml2js.Parser();
var connection = mysql.createConnection({
host : config.mysql.host,
user : config.mysql.user,
password : config.mysql.password,
database : config.mysql.db
});
connection.connect(function(err) {
if (err) { //throw error
console.error(err.stack);
throw err;
}else{
console.log("Succesfully connected to the database!");
// Get Folders in Folder and iterate through every of them
var dirs = getDirectories(config.misc.path);
dirs.forEach(function(dir, index){
var file = config.misc.path + "\\" + dir + "\\" + config.misc.xml_name;
// read xml file of that directory
fs.readFile(file, function(err, data){
parser.parseString(data, function(err, json){
if(err) throw err;
json.resultset.forecast.forEach(function(forecast, index){
forecast.parking_house.forEach(function(ph, index){
var ph_id = ph["$"].id;
ph.estimate.forEach(function(estimate, index){
var value = estimate.value[0]["_"];
var time = estimate.timestamp[0]["_"];
//console.log(time);
connection.query("INSERT INTO lb_data.estimates VALUES (DEFAULT,'23:00:00', 213, 44);", function(error, results, fields){
if(error) throw error;
//Printing %
var perc = (index / dirs.length * 100);
console.log("Scanned and imported " + Math.round(perc) + "% of the files");
});
});
});
});
});
});
});
}
});
/**
* Gets the direcotries in a directory
* #param {string} srcpath the source path of the directory you want to scan
* #return {void}
*/
function getDirectories (srcpath) {
return fs.readdirSync(srcpath)
.filter(file => fs.statSync(path.join(srcpath, file)).isDirectory())
}
Already a big thanks in advance!
PS: Be ensured that the data in config.json is fine, I've tested that outside the loop, so that is not the problem ....

node.js data fetch in json model error

I am new to node.js
I was just making an simple application
my data is inserting properly into the database as well as fetching also from the database
But the problem is when I am trying to access it in json model it is giving me error
var express = require('express');
/*
* body-parser is a piece of express middleware that
* reads a form's input and stores it as a javascript
* object accessible through `req.body`
*
* 'body-parser' must be installed (via `npm install --save body-parser`)
* For more info see: https://github.com/expressjs/body-parser
*/
var bodyParser = require('body-parser');
// create our app
var app = express();
// instruct the app to use the `bodyParser()` middleware for all routes
app.use(bodyParser.urlencoded({ extended: true }));
// A browser's default method is 'GET', so this
// is the route that express uses when we visit
// our site initially.
app.get('/', function(req, res){
// The form's action is '/' and its method is 'POST',
// so the `app.post('/', ...` route will receive the
// result of our form
var html = '<form action="/" method="post">' +
'Enter your name:' +
'<input type="text" name="userName" placeholder="Put your name" />' +
'<br>' +'Enter your city:'+'<input type="text" name="userCity" placeholder="Put your city" />' +
'<br>' +'Enter your state:'+'<input type="text" name="userState" placeholder="Put your state" />' +
'<br>' +'Enter your country:'+'<input type="text" name="userCountry" placeholder="Put your country" />' +
'<br>' +
'<button type="submit">Submit</button>' +
'</form>';
res.send(html);
});
// This route receives the posted form.
// As explained above, usage of 'body-parser' means
// that `req.body` will be filled in with the form elements
app.post('/', function(req, res){
var userName = req.body.userName;
var userCity = req.body.userCity;
var userState = req.body.userState;
var userCountry = req.body.userCountry;
// var document = {userName:userName,userCity:userCity,userState:userState,userCountry:userCountry};
var html = 'Hello: ' + userName + '.<br>' +'City: ' + userCity + '.<br>'+'State: ' + userState + '.<br>'+'country: ' + userCountry + '.<br>'+
'Try again.';
// res.send(html);
//res.send(JSON.stringify(doc));
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = require('mongodb').MongoClient;
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/test';
// Use connect method to connect to the Server
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to', url);
/* var userName = req.body.userName;
var userCity = req.body.userCity;
var userState = req.body.userState;
var userCountry = req.body.userCountry;
var document = {userName:userName, userCity:userCity,userState:userState,userCountry:userCountry};*/
// do some work here with the database.
var insertDocument = function(db, callback) {
db.collection('test').insertOne( {
"userName" :userName,
"userCity" : userCity,
"userState" : userState,
"userCountry" :userCountry ,
}, function(err, result) {
assert.equal(err, null);
console.log("Inserted a document into the test collection.");
callback(result);
});
};
var findDocument = function(db, callback) {
var cursor =db.collection('test').find( );
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.log(doc);
// res.contentType('application/json');
res.send(JSON.stringify(doc));
/* app.get('/test', function(req, res, next) {
res.json(doc);
});*/
} else {
callback();
}
// res.send(JSON.stringify(doc));
});
};
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
insertDocument(db, function() {
findDocument(db, function() {
db.close();
});
});
});
/* var document = {name:"David", title:"About MongoDB"};
db.collection('test').insertOne(document, function(err, records) {
if (err) throw err;
console.log("Record added as "+records[0]._id);
});*/
//Close connection
// db.close();
}
});
});
app.listen(3000);
Please help me to get rid off the problem.
Thank you..
The error I am getting is cann't set headers after they are send
This kind of error usually means that you try using res.send(...) multiple times from the same route.
Here you can see that in your find document, you use a cursor.each, and send your result inside this cursor.each. This means that you send multiple results from the same route.
What you should do instead is having a variable that you use to store your result before sending it once everything is retrieved.

NodeJS MySQL Dump

I've attempted to write a basic cron script to run and 'dump' a mysql database. For some reason, when it 'successfully saves the file', it does create the file, but it is empty. If instead of saving the file, I perform a console.log, it prints an empty string. Any thoughts on what I may be doing wrong?
Thanks in advance.
var mysql_backup = function(){
this.backup = '';
this.mysql = require('mysql'),
this.init = function(){
this.connection = this.mysql.createConnection({
user: 'root',
password: 'root',
database: 'test'
});
}
this.query = function(sql, callback) {
this.connection.query(sql, function (error, results, fields) {
if (error) {
throw error;
}
if (results.length > 0) {
callback(results);
}
});
}
this.get_tables = function(callback){
var me = this;
me.query('SHOW TABLES',
function(tables) {
for (var table in tables){
me.query(
'SHOW CREATE TABLE ' + tables[table].Tables_in_test,
function(r){
for (var t in r) {
me.backup += "DROP TABLE " + r[t].Table + "\n\n";
me.backup += r[t]["Create Table"] + "\n\n";
}
}
)
}
me.save_backup();
});
}
this.save_backup = function(){
var fs = require('fs');
fs.writeFile("./backup_test.txt", this.backup, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
}
};
var db = new mysql_backup;
db.init();
db.get_tables();
db.connection.destroy();
The code as written didn't even get to a file saving for me. There seem like a few issues. Not sure if this is the actual code or some things got lost in the copy paste. However, based on what you've got:
A big one is that you never connect to the database in your code with connection.connect().
The code you want to run once connected should be inside the connection.connect() callback. e.g.
connection.connect(function (err, empty) {
if (err)
throw new Error ('Panic');
// if no error, we are off to the races...
}
However, even if you quickly refactor your code to wrap your last lines inside of that get connection callback, you'll still have problems, because you are destroying the connection before the various SQL calls are getting made, so you will want to move the code into some sort of final callback.
Even after you do that, you'll still have an empty file, because you're calling save_backup from your 'SHOW TABLES' callback rather than after you have actually populated it via the inner callback where you get the CREATE TABLE statement and populate the backup property.
This is the minimal rewriting of your code which will do what you are intending. An important thing to note is the "counter" which manages when to write the file and close the connection. I would make other changes if it were mine, including:
Using 'self' instead of 'me'
Using a numeric for loop rather than the for (... in ...) syntax
Having my own callbacks fall the node convention of (err, stuff)
A more substantial changes is that I would rewrite this to use promises, as doing so can spare you some grief with the confusion inherent with deeply nested callbacks. I personally like the Q library, but there are several options here.
Hope this helped.
var mysql_backup = function(){
this.backup = '';
this.mysql = require('mysql');
this.init = function(){
this.connection = this.mysql.createConnection({
user : 'root',
password : 'root',
database : 'test'
});
};
this.query = function(sql, callback) {
this.connection.query(sql, function (error, results, fields) {
if (error) {
throw error;
}
if (results.length > 0) {
callback(results);
}
});
};
this.get_tables = function(callback){
var counter = 0;
var me = this;
this.query('SHOW TABLES',
function(tables) {
for (table in tables){
counter++;
me.query(
'SHOW CREATE TABLE ' + tables[table].Tables_in_mvc,
function(r){
for (t in r) {
me.backup += "DROP TABLE " + r[t].Table + "\n\n";
me.backup += r[t]["Create Table"] + "\n\n";
}
counter--;
if (counter === 0){
me.save_backup();
me.connection.destroy();
}
}
)
}
});
};
this.save_backup = function(){
var fs = require('fs');
fs.writeFile("./backup_test.txt", this.backup, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
}
};
var db = new mysql_backup;
db.init();
db.connection.connect(function (err){
if (err) console.log(err);
db.get_tables(function(x){;});
});
Update: If you are curious, here is a heavily-commented implementation using promises. Note that without the comments explaining the Q promise library functions, it is somewhat shorter than the original version and also offers more comprehensive error handling.
var MysqlBackup = function(connectionInfo, filename){
var Q = require('q');
var self = this;
this.backup = '';
// my personal preference is to simply require() inline if I am only
// going to use something a single time. I am certain some will find
// this a terrible practice
this.connection = require('mysql').createConnection(connectionInfo);
function getTables(){
// return a promise from invoking the node-style 'query' method
// of self.connection with parameter 'SHOW TABLES'.
return Q.ninvoke(self.connection,'query', 'SHOW TABLES');
};
function doTableEntries(theResults){
// note that because promises only pass a single parameter around,
// if the 'denodeify-ed' callback has more than two parameters (the
// first being the err param), the parameters will be stuffed into
// an array. In this case, the content of the 'fields' param of the
// mysql callback is in theResults[1]
var tables = theResults[0];
// create an array of promises resulting from another Q.ninvoke()
// query call, chained to .then(). Note that then() expects a function,
// so recordEntry() in fact builds and returns a new one-off function
// for actually recording the entry (see recordEntry() impl. below)
var tableDefinitionGetters = [];
for (var i = 0; i < tables.length ; i++){
// I noticed in your original code that your Tables_in_[] did not
// match your connection details ('mvc' vs 'test'), but the below
// should work and is a more generalized solution
var tableName = tables[i]['Tables_in_'+connectionInfo.database];
tableDefinitionGetters.push(Q.ninvoke(self.connection, 'query', 'SHOW CREATE TABLE ' + tableName)
.then(recordEntry(tableName)) );
}
// now that you have an array of promises, you can use Q.allSettled
// to return a promise which will be settled (resolved or rejected)
// when all of the promises in the array are settled. Q.all is similar,
// but its promise will be rejected (immediately) if any promise in the
// array is rejected. I tend to use allSettled() in most cases.
return Q.allSettled(tableDefinitionGetters);
};
function recordEntry (tableName){
return function(createTableQryResult){
self.backup += "DROP TABLE " + tableName + "\n\n";
self.backup += createTableQryResult[0][0]["Create Table"] + "\n\n";
};
};
function saveFile(){
// Q.denodeify return a promise-enabled version of a node-style function
// the below is probably excessively terse with its immediate invocation
return (Q.denodeify(require('fs').writeFile))(filename, self.backup);
}
// with the above all done, now you can actually make the magic happen,
// starting with the promise-return Q.ninvoke to connect to the DB
// note that the successive .then()s will be executed iff (if and only
// if) the preceding item resolves successfully, .catch() will get
// executed in the event of any upstream error, and finally() will
// get executed no matter what.
Q.ninvoke(this.connection, 'connect')
.then(getTables)
.then(doTableEntries)
.then(saveFile)
.then( function() {console.log('Success'); } )
.catch( function(err) {console.log('Something went awry', err); } )
.finally( function() {self.connection.destroy(); } );
};
var myConnection = {
host : '127.0.0.1',
user : 'root',
password : 'root',
database : 'test'
};
// I have left this as constructor-based calling approach, but the
// constructor just does it all so I just ignore the return value
new MysqlBackup(myConnection,'./backup_test.txt');