Parsing nested JSON using body-parser and express - javascript

I have an iOS app which is sending a JSON packet to a webserver. The webserver code looks like this:
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var app = express();
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log("MongoDB connection is open.");
});
// Mongoose Schema definition
var Schema = mongoose.Schema;
var LocationSchema = new Schema({
X: Number,
Y: Number,
Orientation: Number,
UserID: String,
Time: String
});
// Mongoose Model definition
var LocationsCollection = mongoose.model('locations', LocationSchema);
// create application/json parser
var jsonParser = bodyParser.json();
// URL management
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
app.post('/update', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
else {
console.log(req.body);
}
});
// Start the server
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('App listening at %s:%s',host, port)
});
The key part is the app.post method which processes the incoming http request being sent from my iOS app. At the moment, the method which prints the req.body to the console looks like this:
{
datapoint_1:
{ timestamp: '2015-02-06T13:02:40:361Z',
x: 0.6164286615466197,
y: -0.6234909703424794,
id: 'B296DF8B-6489-420A-97B4-6F0F48052758',
orientation: 271.3345946652066 },
datapoint_2:
{ timestamp: '2015-02-06T13:02:40:961Z',
x: 0.6164286615466197,
y: -0.6234909703424794,
id: 'B296DF8B-6489-420A-97B4-6F0F48052758',
orientation: 273.6719055175781 }
}
So, you can see the request is a nested JSON object. Ideally, I'd like to loop through the request objects (ie. the datapoints) and insert those into the mongoDB database (via mongoose). However, I can't seem to figure out how to do much of anything with the req.body. I can't seem to create a loop to iterate through the request or how to properly parse the nested JSON file so it matches the mongoose schema. Can anyone provide some guidance on how to insert these datapoints into the mongoose database?

Set body-parser's extended property to true to allow parsing nested objects.
var express = require('express');
var app = express()
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));

Answering my own question. But, after figuring out how to access the key/value pairs inside the nested JSON object... it became relatively easy to figure out the rest. The updated app.post function now looks like this:
app.post('/update', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
else {
for(var datapoint in req.body){
//create new instance of LocationCollection document
var point = new LocationsCollection({
X:Number(req.body[datapoint]["x"]),
Y:Number(req.body[datapoint]["y"]),
Orientation:Number(req.body[datapoint]["orientation"]),
Time:req.body[datapoint]["timestamp"],
UserID:req.body[datapoint]["id"]
});
//insert the newly constructed document into the database
point.save(function(err, point){
if(err) return console.error(err);
else console.dir(point);
});
}
}
});
I can test if this worked by putting the following method inside the callback function once the mongodb connection is first established:
//Find all location points and print to the console.
console.log("Searching for all documents in Location Points Collection");
LocationsCollection.find(function(err,data){
if(err) console.error(err);
else console.dir(data);
});
This will print any documents that have been previously added to the database. Hopefully this helps.

Try somthing like this.
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit:1024*1024, verify: function(req, res, buf){
try {
JSON.parse(buf);
} catch(e) {
res.send({
error: 'BROKEN_JSON'
});
}
}}));

It should be a simple for (var key in obj) loop:
app.post('/update', jsonParser, function (req, res) {
var locationObject = req.body(),
insertObjects = [],
key;
for (key in locationObject) { // loop through each object and insert them into our array of object to insert.
insertObjects.push(locationObject[key]);
}
if (!insertObjects.length) { // if we don't have any object to insert we still return a 200, we just don't insert anything.
return res.status(200).send({
success: true,
message: 'Nothing inserted, 0 locations in POST body',
count: 0;
});
}
LocationsCollection.create(insertObjects, function (err, res) {
if (err) {
return res.status(400).send({
success: false,
message: err.message
});
}
// we have successfully inserted our objects. let's tell the client.
res.status(200).send({
success: true,
message: 'successfully inserted locations',
count: insertObjects.length;
});
});
});
Mongo allows for inserting multiple documents with a single callback, which makes this a lot easier.
This also checks the schema to ensure only proper documents are created.

Related

router.post can't pass data

$.post($gameNetwork._serverURL+'/addfriend',
{username:"r",tusername:"w"}).done(function (data) {
console.log("finished");
});
Account.statics.
friend = function(name,tname,cb) {
return this.findOneAndUpdate(
{ 'username': name },
{ $push: {'friendlist': tname}},
{ upsert: true, new: true},
cb);
};
route
router.post('/addfriend', function(req, res) {
//Account.findByName(req.body.username, function(err, account){
Account.friend(req.body.username,req.body.tusername, function(err, account){
if (err) {
return res.status(203).json({
err: err.msg
});}
if (!account) {
return res.status(203).json({
err: "Invalid username"
});}
var tname = req.body.tusername;
var profile = {
tname : tname,
name: account.username,
email: account.email,
id: account._id,
rank: account.rank
}; });
this code should enter "w" in to the field 'friendlist' in Mongodb, but I got null instead of w.
how can I get "w" into the field 'friendlist' in Mongodb.
Any help is appreciated
Thanks in advance
router in an ExpressJS router?
If yes did you set the bodyParser middleware?
If not, set it like this
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
// parse application/json
app.use(bodyParser.json())
You can also try to stringify the body in the ajax request like described here
You can debug your data of request like this:
router.post('/addfriend', function(req, res) {
console.log(req.body);
// your logic
}
Run your code again, and you can see your data that you expect. If you see tusername = null or undefined, may be the problem in configure of your module that you use, example body-parser, busboy...vv
All comments are welcome!

Accessing user information in Express JS is returning Undefined

I am currently using Passport for authentication within my application. When trying to pull a users email in order to store in my db along with other information, I get a returned value of undefined. If I pull the entire user object I get the correct information though. See below.
Here is the server.js file initializing the session.
app.use(session({
secret: 'sessionSecret'
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
Here is the route information
app.get('/itemCreation', function (req, res) {
res.render('itemCreation.ejs', {
user: req.user
});
});
app.post('/itemCreation', function (req, res) {
var item = new itemSchema();
item.local.productName = req.body.productName;
item.local.itemPrice = req.body.itemPrice;
item.local.Quantity = req.body.Quantity;
item.local.Description = req.body.Description;
console.log(req.user.firstName);
item.save(function (err) {
if (err)
throw err;
else
console.log('Saved item information successfully');
});
res.redirect('/shop');
});
Here is my Item model
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var itemSchema = mongoose.Schema({
local : {
productName : String,
itemPrice : Number,
Quantity : Number,
Description : String
}
});
module.exports = mongoose.model('item', itemSchema);
Here is the result of pulling the whole object, which I get by calling
console.log(req.user);
and here is the result of pulling just the email from the object, which I get by calling
console.log(req.user.email);
It shoud be console.log(req.user.local.email);

insert user data into mongodb database

I am trying to insert data into a mongodb database.
I am able to submit user data and display it with...
app.get('/process_get', function (req, res) {
response = {
first_name:req.query.firstName,
last_name:req.query.lastName,
username:req.query.userName,
password:req.query.password,
email:req.query.email
};
console.log(response);
res.end(JSON.stringify(response));
})
I then opened a connection with mongodb and created a "test" collection successfully...
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) { return console.dir(err); }
if(!err) { console.log("MongoDB server is connected!") }
var collection = db.collection('test');
})
I tried "collection.insert({name:req.query.firstName});"
but this obviously didn't work because no "req". How do I make the inputs global
so I can simply insert them?
You don't have to do this within the database connection callback. Simply connect to your database in the process and then invoke the models.
//Setup Server and connect to mongoDB
var app = require('express')();
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
mongoose.connect('mongodb://localhost:27017/exampleDb');
//Create the model
var testSchema = mongoose.Schema({
..
});
var Test = mongoose.model('test', testSchema);
//Now use the model to save the object in the route controller
app.get('/process_get', function (req, res) {
response = {
.. //build the object based on some input or pas req.body directly
};
console.log(response);
new Test(response).save().then(function(result) {
res.end(JSON.stringify(result));
});
});
NB! You should split this logic out in different files to keep your project easier to maintain. The only reason for me to have it all in one file is to remove complexity.

Mongoose: .save is not a function

I'm very new and I've looked through the archives but just what's going on in this code eludes me. I used express-generator to create a calendar app and now I want to hook it up to MongoDB. The actual connection to Mongo is working, but I can't get it to save a document.
The relevant portion of my global.js (where I'm running my front-end Javascript) looks like this:
$(document).ready(function() {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
This is where I'm getting the "TypeError: ev.save is not a function" message. My models/Events.js looks like this:
var mongoose = require('mongoose');
var eventSchema = new mongoose.Schema({
date: String,
time: Number,
description: String
});
module.exports = mongoose.model('Event', eventSchema);
My routes/events.js looks like this:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Event = require('../models/Events.js');
/* GET /event listing. */
router.get('/', function(req, res, next) {
Event.find(function (err, dates) {
if (err) return next(err);
res.json(dates);
});
});
/*POST event*/
router.post('/', function(req, res, next) {
Event.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* GET /event/id */
router.get('/:id', function(req, res, next) {
Event.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
I want to save something to test it, but it's giving me ".save is not a function. Other than
var events = require('./routes/events');
app.use('/events', events);
and the code establishing the Mongoose connection my app.js file is boilerplate. What do you think is the problem?
I see
$(document).ready(function() {
Are you trying to use Mongoose in browser?
It's supposed to be used on the server-side.
In browser you need to send AJAX request to the server:
$('#save').click(function() {
$.post('/event', function(response) { console.log(reposne) })
});
On the server you should add a route that will handle your AJAX request, and inside this route you can save your model:
router.post('/event', function(req, res) {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
});
Please note that you don't need the 3rd param next in your rotues. It is used only in middlewares
Are you sure that line
var Event = require('../models/Events.js');
has the correct path?
You are creating an ev object from Event function and it seems that ev is undefined, judging from the error description.
If your Event file is not properly loaded you will not have access to .save function.

can't create a new directory using mongoose and express

Like the title entails.
I'm trying to make an application that when i put in certain info, it creates a link using mongoose _id. and express's app.get what i don't get is that to be able to join that directory i have to reload the whole server, which for the users and my sake a i don't want to do.
var mongoose = require("mongoose");
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
var router = express.Router();
app.get("/", function (req, res) {
var ip = req.connection.remoteAddress;
res.sendFile(__dirname + "/index.html");
});
mongoose.connect("mongodb://localhost:27017/NEW_DB1");
console.log("Connection to database has been established");
var collectedData = new mongoose.Schema({
ipAddress: String,
name: {
type: String,
unique: false
}
});
var collectionOfData = mongoose.model("dataType", collectedData);
io.on("connection", function (socket) {
socket.on("name", function (e) {
var ip = socket.request.socket.remoteAddress;
var dataBase = mongoose.connection;
var Maindata = new collectionOfData({
ipAddress: ip,
name: e
});
Maindata.save(function (err, Maindata) {
if (err) {
return console.error(err);
} else {
console.dir(Maindata);
}
});
});
});
app.get("/mix", function (req, res) {
collectionOfData.find(function (err, data) {
res.send(data);
});
});
collectionOfData.find(function (err, data) {
data.forEach(function (uniqueURL) {
app.get("/" + uniqueURL._id, function (req, res) {
res.send("<h1>Hello " + uniqueURL.ipAddress + "</h1><p>" + uniqueURL.name + "</p>");
});
});
});
http.listen(10203, function () {
console.log("Server is up");
});
So what i'm trying to do is make it so i don't have to reload the whole server, and i'm able to just join the created directory when it's done being loaded.
figured i should put a quick example:
localhost:10203/55c2b2f39e09aeed245f2996
is a link a user just created the long
55c2b2f39e09aeed245f2996
is the effect of the _id, but when the user try's to connect to that site it won't work until i reload the server and obviously i'd like to avoid that haha.
I have a index.html file, but all that has is a socket.emit that sends "name" to the server
app.get("/", function (req, res) {
var ip = req.connection.remoteAddress;
res.sendFile(__dirname + "/index.html");
});
app.get('/:uniqueURL', function(req, res){
var id = req.params.uniqueURL;
res.send("Your requested id : " + id);
})
Try to use this above.
You are creating fix get path inside collectionData.find. That is the problem. So each time you have to reload the server by restarting.

Categories