I have this basic nodejs script:
var express = require('express'),
Sequelize = require('sequelize'),
promise = require('bluebird'),
app = express(),
optimus = new Sequelize('optimus', 'root', 'test', {host: '127.0.0.1', dialect: 'mysql'}),
query = 'SELECT id FROM borrowers LIMIT 0,10',
query2 = 'SELECT COUNT(*) FROM borrowers';
app.get('/', function(req,res) {
var chain = new Sequelize.Utils.QueryChainer();
console.log('begin');
chain.add(optimus, 'query', [query,null,null,[]])
.add(optimus, 'query', [query2,null,null,[]])
.run()
.success(function() {
console.log('done');
}).error(function(err) {
console.log('oh no');
});
console.log('end');
res.send('Hi Ma!');
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
}
);
Neither 'done' nor 'oh no' ever fires which leads me to believe that I can' chain raw queries in this manner.
What I'd really like to accomplish is to asynchronously resolve both queries and pass the results back via res.send().
I have to admit to being a complete n00b at nodejs so any insights into how to correctly structure this would be greatly appreciated.
The major issue with your code is the fact, that you are sending a response to the client/browser too early. Instead of res.send-ing at the end of the app.get method, you need to send the answer inside the success respectively inside the error callback. Here you are:
var express = require('express'),
Sequelize = require('sequelize'),
promise = require('bluebird'),
app = express(),
optimus = new Sequelize('sequelize_test', 'root', null, {host: '127.0.0.1', dialect: 'mysql'}),
query = 'SELECT id FROM borrowers LIMIT 0,10',
query2 = 'SELECT COUNT(*) as count FROM borrowers';
app.get('/', function(req,res) {
var chain = new Sequelize.Utils.QueryChainer();
console.log('begin');
chain
.add(optimus.query(query, null, { raw: true }))
.add(optimus.query(query2, null, { raw: true, plain: true }))
.run()
.success(function(results) {
res.send({
resultOfQuery1: results[0],
resultOfQuery2: results[1]
});
}).error(function(err) {
console.log('oh no', err);
});
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
}
);
Please notice, that I changed the credentials to my local ones. Furthermore also check the arguments of chain.add. Instead of passing the values for an upcoming serial executation, we just throw the actual asynchronous methods into it and let the querychainer handle their promises.
Related
I was familiar with MongodB for CRUD operation. Here, I'm trying to make simple post request on mongodB atlas but I want to know where I have done error for the connection and posting data to MongodB atlas.
Model.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
let quizSchema = new Schema({
title: {
type: String,
},
description: {
type: Number,
},
question: {
type: String,
},
});
const Quiz = mongoose.model("Quiz", quizSchema);
module.exports = Quiz;
index.js
I'm trying to create the database collection name "QuizDatabase" and insert the data to it.
var express = require("express");
var bodyParser = require("body-parser");
const Quiz = require("./views/model/model");
var Request = require("request");
var app = express();
app.use(bodyParser.json());
const MongoClient = require("mongodb").MongoClient;
const uri =
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.connect(uri);
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post("/new/", function (req, res) {
Quiz.collection("QuizDatabase").insertMany(req.body, function (err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new quiz.");
} else {
res.status(201).send(JSON.stringify(body));
}
});
});
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({ error: message });
}
You dont have to use mongo client if you are already using mongoose.
In index.js file just import the model
const Quiz = require("./model");
And you are already using mongoose to connect to db when you write mongoose.connect(uri); You don't have to use client.connect() again.
Query to insert -
Quiz.insertMany(req.body);
Your index file should look like this -
const Quiz = require("./views/model/model");
var Request = require("request");
var app = express();
app.use(bodyParser.json());
const uri =
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
mongoose.connect(uri);
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post("/new/", function (req, res) {
Quiz.insertMany(req.body, function (err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new quiz.");
} else {
res.status(201).send(JSON.stringify(body));
}
});
});
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({ error: message });
}
There are several reasons.
Connection Issues to the MongoDB database.
To check this insert app.listen() into mongoose connect. This would make sure you can only run development on your preferred PORT only when it has successfully connected to your Database. e.g From your code
mongoose.connect(uri)
.then(() => {
//listen for PORT request
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
}).catch((error) => {
console.log(error);
});
Try purposely using the wrong Username or Password and see if you get this error:
MongoServerError: bad auth : Authentication failed.
at Connection.onMessage (/Users/user/Documents/..<pathway>../connection.js:207:30)
*
*
*
*
ok: 0,
code: 8000,
codeName: 'AtlasError',
[Symbol(errorLabels)]: Set(1) { 'HandshakeError' } }
If you don't get this error then you have a connection problem. To solve this, I added my current IP ADDRESS and 0.0.0.0/0 (includes your current IP address) at the Network Access page. So you click on MY CURRENT IP ADDRESS and confirm upon setting up the network. Go to NETWORK ACCESS, click on add new IP ADDRESS, input 0.0.0.0/0 and confirm. Then try using the wrong username or password in the URI link given to you to see if it gives the above-expected error, then you can now correct the Username and Password, and npm run dev or npm start (However you configured it in your package.json file).
Code issues
First of I would correct your Model.js file from this:
const Quiz = mongoose.model("Quiz", quizSchema);
module.exports = Quiz;
to this:
module.exports = mongoose.model("Quiz", quizSchema);
I can see why yours can work, but it may be an issue as you want to get the schema upon accessing the whole file.
Secondly, I would correct the code for Posting and you can do that in 2 ways using the asynchronous method. Which depends on the method of assigning the req.body.
Way 1:
app.post("/new/", async (req, res) => {
const { title, description, question } = req.body;
//adds doc to db
try {
const quiz = await Quiz.create({ title, description, question });
res.status(200).json(quiz);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
OR
Way2:
app.post("/new/", async (req, res) => {
const quiz = new Quiz(req.body);
//adds doc to db
try {
const savePost = await quiz.save();
response.status(200).send(savePost);
} catch (error) {
response.status(400).send(error);
}
});
NOTE: You don't necessarily have to create a named database and collection in Mongo Atlas before starting the project. The URI given to you covers that if there are no problems with the connection to the DB or the Code.
based on your code
URI:
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
would create a database called: QuizDatabase and collection called: quizs (MongoDb always creates the plural word from the model given and makes it start with lowercase (i.e from your Model.js, the mongoose.model("Quiz"))).
If no database is named in your URI, then a database called test is automatically created for you as a default database, with the collection name being the mongoose.model("") given.
CONCLUSION
This should solve at least 90% of your issues, any other creation/POST problems is currently beyond my current expertise. Happy Coding 🚀🚀🚀
I need to create a simple solution to receive input from an user, query our database and return the result in any way, but the queries can take as long as half an hour to run (and our cloud is configured to timeout after 2 minutes, I'm not allowed to change that).
I made the following solution that works locally, and want to include code to send the query's result via email to the user (in a fire and forget manner), but am unsure as how to do that while returning HTTP 200 to the user.
index.js:
const express = require('express')
const bodyParser = require('body-parser')
const db = require('./queries')
const app = express()
const port = 3000
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
app.get('/', (request, response) => {
response.json({ info: 'Node.js, Express, and Postgres API' })
})
app.post('/report', db.getReport)
app.get('/test', db.getTest)
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
queries.js:
const Pool = require('pg').Pool
const pool = new Pool({
user: 'xxx',
host: 'xx.xxx.xx.xxx',
database: 'xxxxxxxx',
password: 'xxxxxxxx',
port: xxxx,
})
const getReport = (request, response) => {
const { business_group_id, initial_date, final_date } = request.body
pool.query(` SELECT GIANT QUERY`, [business_group_id, initial_date, final_date], (error, results) => {
if (error) {
throw error
}
response.status(200).json(results.rows)
})
// I want to change that to something like:
// FireNForgetWorker(params)
// response.status(200)
}
module.exports = {
getReport
}
Through the use of callbacks, and based on the design of express, you can send a response and continue to perform actions in that same function. You can, therefore, restructure it to look something like this:
const Pool = require('pg').Pool
const pool = new Pool({
user: 'xxx',
host: 'xx.xxx.xx.xxx',
database: 'xxxxxxxx',
password: 'xxxxxxxx',
port: xxxx,
})
const getReport = (request, response) => {
const { business_group_id, initial_date, final_date } = request.body
pool.query(` SELECT GIANT QUERY`, [business_group_id, initial_date, final_date], (error, results) => {
if (error) {
// TODO: Do something to handle error, or send an email that the query was unsucessfull
throw error
}
// Send the email here.
})
response.status(200).json({message: 'Process Began'});
}
module.exports = {
getReport
}
=============================================================================
Another approach could be to implement a queuing system that would push these requests to a queue, and have another process listening and sending the emails. That would be a bit more complicated though.
I'm learning Node js and I'd like to understand why the output or result set is showing twice in the browser (tried with different browsers) and how to fix the issue to show the result set only once.
Here is my sample code :
// JavaScript source code
var express = require('express'); // Web Framework
var app = express();
var sql = require('mssql'); // MS Sql Server client
// Connection string parameters.
const pool = new sql.ConnectionPool({
user: 'myuser',
password: 'password123',
server: 'localhost',
database: 'Sample'
})
var conn = pool;
// Start server and listen on http://localhost:8080/
var server = app.listen(8080, function () {
var host = server.address().address
var port = server.address().port
console.log("app listening at http://%s:%s", host, port)
});
app.get('/groups', function (req, res) {
conn.connect().then (function() {
var request = new sql.Request(conn);
request.query('SELECT TOP 10 * FROM [Sample].[Table1]',function(err, recordset) {
if(err) console.log(err);
res.end(JSON.stringify(recordset)); // Result in JSON format
conn.close();
});
});
})
please advice.
Thanks.
I have a simple code that gives a JSON response for a specific route. Here's my current code:
var express = require('express')
, async = require('async')
, http = require('http')
, mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: '****',
password: "****",
database: 'restaurants'
});
connection.connect();
// all environments
app.set('port', process.env.PORT || 1235);
app.use(express.static(__dirname + '/public/images'));
app.get('/DescriptionSortedRating/',function(request,response){
var name_of_restaurants;
async.series( [
// Get the first table contents
function ( callback ) {
connection.query('SELECT * FROM restaurants ORDER BY restaurantRATING', function(err, rows, fields)
{
console.log('Connection result error '+err);
name_of_restaurants = rows;
callback();
});
}
// Send the response
], function ( error, results ) {
response.json({
'restaurants' : name_of_restaurants
});
} );
} );
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
How can I make an XML response equivalent to the JSON above?
You can use any number of the XML libraries available on npm. Here's an example using the simply-named "xml" library:
var xml = require('xml');
response.set('Content-Type', 'text/xml');
response.send(xml(name_of_restaurants));
See the module's documentation for a description of how it converts JavaScript objects to XML. If you need things returned in a specific XML format, you'll have more work to do, of course.
As an update to this, it looks like res.type should be used instead as res.set does not give the same results.
res.type('application/xml');
More information can be found in the API reference.
I want to know how ExpressJS works in the server side
I need some information on Server side, Main things are,As per my knowledge,
ExpressJS can perform all the functionalists of a PHP - - - IS it
true ?
My Client(Android) is ready to submit a POST request to Server
If i can send one single information in the form of (Key,value) pair,
can the Express accept that pair- - Identify the value based on key
and, to perform a sql query to Database based on the value received
from android client?
If it can how it does it?
MY Express Program ( It gives a Response without scenario explained above - How to modify this program )
var express = require('express')
, async = require('async')
, http = require('http')
, mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: '*********',
password: "*****",
database: 'DB'
});
connection.connect();
// all environments
app.set('port', process.env.PORT || 7002);
//
//REQUEST FOR FIRST REQUEST
//
app.get('/',function(request,response){
var name_of_restaurants, RestaurantTimings;
async.series( [
// Get the first table contents
function ( callback ) {
connection.query('SELECT * FROM restaurants', function(err, rows, fields)
{
console.log('Connection result error '+err);
name_of_restaurants = rows;
callback();
});
},
// Get the second table contents
function ( callback ) {
connection.query('SELECT * FROM RestaurantTimings', function(err, rows, fields)
{
console.log('Connection result error '+err);
RestaurantTimings = rows;
callback();
});
}
// Send the response
], function ( error, results ) {
response.json({
'restaurants' : name_of_restaurants,
'RestaurantTimings' : RestaurantTimings
});
} );
} );
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Hope I am clear
Thanks ,
You can send information via query params or as part of the url path. If you send it as a query param, you can access it using
req.query.keyName;
If you want to send the value as part of the url, you'll have to add a route to accept it. You can accept variable content in a url by using the :keyName form. Express will capture it in req.params. So it would look a little like this:
app.get('/some/url/:keyName', function(req, res, next){
var keyName = req.params.keyName;
// . . .
});
Then you can send your http request to '/some/url/someKeyValue' and the variable keyName will then be equal to whatever you add after /some/url/.
If you're POSTing data in the body of the request, access it with req.body.keyName.
EDIT: Here's an attempt at using the original code. Note that I'm still making up values and guessing at what the intent is.
var express = require('express')
, async = require('async')
, http = require('http')
, mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: '*********',
password: "*****",
database: 'DB'
});
connection.connect();
// all environments
app.set('port', process.env.PORT || 7002);
//
//REQUEST FOR FIRST REQUEST
//
app.get('/',function(request,response){
var name_of_restaurants, RestaurantTimings;
async.series( [
// Get the first table contents
function ( callback ) {
connection.query('SELECT * FROM restaurants WHERE name = ' . request.body.name, function(err, rows, fields) {
console.log('Connection result error '+err);
name_of_restaurants = rows;
callback();
});
},
// Get the second table contents
function ( callback ) {
connection.query('SELECT * FROM RestaurantTimings', function(err, rows, fields) {
console.log('Connection result error '+err);
RestaurantTimings = rows;
callback();
});
}
// Send the response
], function ( error, results ) {
response.json({
'restaurants' : name_of_restaurants,
'RestaurantTimings' : RestaurantTimings
});
} );
} );
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
But you should really not query directly like that because of SQL injection. I've never used MySQL from node, but I'm sure there is some way to use parameterized queries. Hope this is more helpful.
Also, I'm assuming that the data will be passed in the request body, since you said you are ready to POST to the server.