I am trying to get JSON from an API and store it into a MongoDB database.
Obviously, it doesn't work. My app seems to hang around the point where I try to save the data to the database. Please advise what to do.
Here's my code:
var express = require('express');
var router = express.Router();
var http = require('http');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/zak", {native_parser : true});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var site = 'http://www.vsechnyzakazky.cz/api/v1/zakazka/?format=json&limit=2';
function getData(cb) {
http.get(site, function(res) {
// explicitly treat incoming data as utf8 (avoids issues with multi-byte chars)
res.setEncoding('utf8');
// incrementally capture the incoming response body
var body = '';
res.on('data', function(d) {
body += d;
});
// do whatever we want with the response once it's done
res.on('end', function() {
try {
var parsed = JSON.parse(body);
} catch (err) {
console.error('Unable to parse response as JSON', err);
return cb(err);
}
// pass the relevant data back to the callback
cb(
parsed.objects
);
});
}).on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
cb(err);
});
}
function writeData (data, allGood){
// couple of visual checks if all looking good before writing to db
console.log('writing');
console.log(typeof data);
console.log(data);
db.collection('zakazky').save(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
}
function allGood(){console.log('all done');}
getData(writeData);
// ---------------------
module.exports = router;
You are calling the save() instead of insert(). Change this part and it will work:
// this should call insert, not save
db.collection('zakazky').insert(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
Related
Trying to make a simple rest service. The rest service is for pulling up a table from a local database. This rest service a want to make available for an android app.
Having trouble getting passed .then block. Tried catching the error but with no success. How do you catch the error if it's going wrong in the first .then
The below piece of code is the db.js, and sets up the connection to the database.
var sqlDb = require("mysql");
var settings = require("../settings");
exports.executeSql = function (sql, callback) {
var conn = new sqlDb.createConnection(settings.dbConfig);
conn.connect()
// !! Error unhandled
.then(function () {
var req = new sqlDb.Request(conn);
req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
};
After setting up connection the below piece of code is executed. With error handling.
var db = require("../core/db");
exports.getList = function (req, resp) {
db.executeSql("SELECT * FROM employees", function (data, err) {
if (err) {
// throws back error to web
resp.writeHead(500, "Internal Error", { "Content-Type":
"application/json" });
resp.write(JSON.stringify({ data: "ERROR occurred:" + err }));
} else {
resp.writeHead(200, { "Content-Type": "application/json" });
resp.write(JSON.stringify(data));
}
resp.end();
});
};
Made a separated js file for settings such as database. Tested my connection to the db on a same way. Excluded that problem but it keeps returning an error unhandled on the first .then. I'm not familiar with methods till now.
I think I found the problem. new sqlDb.Request(conn); The .Request is not available when using mysql. But how can I fix this
If you catch() an error it will not be caught again without returning a new rejection. Like this:
conn.connect()
.then(function () {
var req = new sqlDb.Request(conn);
// note the "return" here
return req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log(err);
callback(null, err);
// note the line below
return Promise.reject(err)
});
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
};
PS. Do you really need the callback(), why not use the Promise?
I want to create the rest api using node.js and mongodb
I am entering all the details and trying it to store it in the mongodb database.
// call the packages we need
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var morgan = require('morgan');
// configure app
app.use(morgan('dev')); // log requests to the console
// configure body parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 8080; // set our port
var mongoose = require('mongoose');
// mongoose.connect('mongodb://node:node#novus.modulusmongo.net:27017/Iganiq8o'); // connect to our database
mongoose.connect('mongodb://localhost:27017');
var Bear = require('./app/models/bear');
// create our router
var router = express.Router();
// middleware to use for all requests
router.use(function(req, res, next) {
// do logging
console.log('Something is happening.');
next();
});
// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
// on routes that end in /bears
// ----------------------------------------------------
router.route('/bears')
// create a bear (accessed at POST http://localhost:8080/bears)
.post(function(req, res) {
var bear = new Bear(); // create a new instance of the Bear model
bear.name = req.body.name; // set the bears name (comes from the request)
bear.email= req.body.email; // set the bears email(comes from the request)
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear created!' });
});
})
// get all the bears (accessed at GET http://localhost:8080/api/bears)
.get(function(req, res) {
Bear.find(function(err, bears) {
if (err)
res.send(err);
res.json(bears);
});
});
// on routes that end in /bears/:bear_id
// ----------------------------------------------------
router.route('/bears/:bear_id')
// get the bear with that id
.get(function(req, res) {
Bear.findById(req.params.bear_id, function(err, bear) {
if (err)
res.send(err);
res.json(bear);
});
})
// update the bear with this id
.put(function(req, res) {
Bear.findById(req.params.bear_id, function(err, bear) {
if (err)
res.send(err);
bear.name = req.body.name;
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear updated!' });
});
});
})
// delete the bear with this id
.delete(function(req, res) {
Bear.remove({
_id: req.params.bear_id
}, function(err, bear) {
if (err)
res.send(err);
res.json({ message: 'Successfully deleted' });
});
});
// REGISTER OUR ROUTES -------------------------------
app.use('/api', router);
// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);
The Model is given below:-
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BearSchema = new Schema({
name: String,
email: String
});
module.exports = mongoose.model('Bear', BearSchema);
I am trying it to save the name and the email in the mongodb database but only _id is created instead of name, email.
Here is the result:-
[
{
"_id": "567f1f92db24304013000001",
"__v": 0
},
{
"_id": "567f2765db24304013000002",
"__v": 0
}
]
Can anybody tell me why the data are not getting saved in the database.
Please kindly help.
Thanks in Advance.
I think your POST request is not good, so I made this simple script to check it out:
var XHR = (function() {
var _xhr = (function() {
try {
return new(this.XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
} catch (e) {}
})();
return function(method, url, params, callback) {
_xhr.onreadystatechange = function() {
if (_xhr.readyState == 4) {
var _response;
try {
_response = JSON.parse(_xhr.response);
} catch (e) {
_response = _xhr.responseText;
}
if (_xhr.status != 200) {
// catch an error
console.error('error', response);
} else {
if (callback) {
callback(_response);
} else {
// deal with it
}
}
}
}
if (!params) {
params = JSON.stringify({});
} else {
params = JSON.stringify(params);
}
_xhr.open(method, url, true);
// just json in this case
_xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8");
_xhr.send(params);
};
})();
fire it up in browser's console, like this
XHR('POST','api/bears', { name:'yogi', email:'yogi#bears.com'}, function(){ console.log(arguments) });
and your record will be saved.
{ "_id" : ObjectId("567e875d068748ee5effb6e0"), "email" : "yogi#bears.com" "name" : "yogi", "__v" : 0 }
Long story short - your code is okay, your POST is not.
Pretty much purely for pedagogical purposes, I'm serving both my front and back end data out of my one node server. Right now, I'm at the point where I've received my client request successfully, created some data based on said request, am able to console log it, etc. Everything is fine up to that point. My issue is that in the event that my data is only an html file, which is being read with the fs library, it will not render on the page when I attempt to serve it out in my res.end() or res.write(). I can see it's exactly what I want and expect when I console log it, but it just doesn't render in the browser. Any help would be appreciated. I've got it set up to where I'm handling my requests in an "if/else" wherein I only have the two scenarios of "/" (home), in which case I serve the html file, and anything else because the server really only needs to handle those two events. Thanks in advance.
Edit. This is what I have so far:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
}
else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
res.end(data);
console.log(input, req.url)
}
else {
fs.readFile("index.html", "utf8", function(err, data) {
console.log("data:" + data);
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
});
}
res.end();
}
I can see the data in the console which, in the last case, is just my HTML file. It just won't render in the page.
How did you attempted to serve the html with res.end() and res.write() ?
I just made a small test here, and this works:
app.js
var http = require('http');
var fs = require('fs');
var html = fs.readFileSync('hello-world.html');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(html);
}).listen(8000);
hello-world.html
<h3>Hello World</h3>
Edit: To match with your code, try this:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
} else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
console.log(input, req.url);
// we have no data variable in this scope
res.end("");
// I added a return statement in each step
// Just to be clear that we don't want to go if any
// condition have fit, since we cannot call res.end()
// more than once
return;
} else {
fs.readFile("index.html", "utf8", function(err, data) {
// error handling
if (err) return res.end(err);
// now we have the data
console.log("data:" + data);
res.end(data);
});
return;
}
}
Serving html in asynchronous way works something like that;
var fs = require('fs');
var http = require('http');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('index.html', function(err, data){
if(err){
return console.log(err);
}
res.end(data);
});
}).listen(8080);
console.log('Server is running on Port: 8080');
There are several files containing JSON data on my server. I want to receive the data contained in those files with a single GET request.
Right now my code looks like this:
app.get('/json', function(req, res){
fs.readFile(__dirname + '/file01.json', function(err, content){
var data01 = content;
});
fs.readFile(__dirname + '/file02.json', function(err, content){
var data02 = content;
});
res.send({file01: data01, file02: data02});
});
I know this is absolutely not the way to do it, the files are still being read when the response is sent, and i'm not sure if data01 and data02 are globally defined.
But then, what is the way to do it?
Should I use a stream? Should I use multiple res.write() instead? Enlighten me.
Perfect fit for async.parallel.
var async = require('async');
app.get('/json', function(req, res) {
var work = {
file01: async.apply(fs.readFile, __dirname + '/file01.json'),
file02: async.apply(fs.readFile, __dirname + '/file02.json')
};
async.parallel(work, function (error, results) {
if (error) {
res.status(500).send(error);
return;
}
//might need string->Object here
results['file01'] = JSON.parse(results['file01']);
results['file02'] = JSON.parse(results['file02']);
res.send(results);
});
});
Use the callback of each readFile to do the next operation:
fs.readFile(__dirname + '/file01.json', function(err, content){
var data01 = content;
//Might be smart to do some err checking here
//if (err) send error
//else read the next file
fs.readFile(__dirname + '/file02.json', function(err, content){
//if (err) again
var data02 = content;
res.send({file01: data01, file02: data02});
});
});
What i'am trying to achieve is to make DB query inside closure. Return data and then send stuff to user. I understand that best practice is to use database pooling. Problem is that query is not sync.
Simplified code:
server.js
var express = require('express'),
app = express(),
server = require('http').createServer(app),
mysql = require('mysql');
app.set('DB:pool', mysql.createPool(process.env.DATABASE_URL));
var myClosure = require('./closure.js')(app));
app.get('/somepage', function(req, res) {
var data = myClosure.myquery();
res.send(data);
});
app.get('/anotherpage', function(req, res) {
var data = myClosure.myquery();
res.send(data);
});
app.listen(3000);
closure.js
function myClosure(app) {
var pool = app.get('DB:pool');
return {
myquery: function(inp) {
pool.getConnection(function(err, db) {
if (err) throw err;
db.query('SELECT * FROM table', function(err, rows, fields) {
if (err) throw err;
data = rows[0]
db.release();
});
});
return data;
}
};
}
module.exports = myClosure;
In examples i found all DB related stuff were made in route callback and response was sent in query callback. But way i'm trying to do it is not working as myquery returns undefined because sql query is not done there.
So what is correct way to handle querys ?
Make your query-function handle a callback too:
// server.js
app.get('/somepage', function(req, res) {
myClosure.myquery(function(err, data) {
// TODO: handle error...
res.send(data);
});
});
// closure.js
...
myquery: function(callback) {
pool.getConnection(function(err, db) {
if (err) return callback(err);
db.query('SELECT * FROM table', function(err, rows, fields) {
// release connection before we return anything, otherwise it
// won't be put back into the pool...
db.release();
if (err) return callback(err);
callback(null, rows[0]);
});
});
}
(I left out the inp argument because that didn't seem to be used)