Attribute not submitting to MongoDB (MERN stack) - node.js

I'm working on an app that assesses students algebra 1 level. I'm trying to send a string called "answers" to the database, but nothing is ever sent. I've shown the model/schema below, where basically each submission should send the answers String (it was originally an object, but I couldn't get an answer to Mongoose not persisting object so I'm just trying a string to see if it even submits a string. The user and date are submitted to the database, but there is not even an entry for the answers attribute. I've seen that the payload sent if I submit a "2" is {"results": "2"} so there's something in the request body. My response back from the server is {} so I think I'm not destructuring a prop correctly or maybe sending an object unintentionally.. Any ideas as to why no answers attribute is submitted to the database? Any help is greatly appreciated!
api/algebra1.js (route to send test results)
const express = require('express');
const router = express.Router();
var bodyParser = require('body-parser')
const bcrypt = require('bcryptjs');
const algebra1 = require('../../models/Algebra1');
const jwt = require('jsonwebtoken');
const config = require('config');
const auth = require('../../middleware/auth');
//#route POST api/auth
//#desc Algebra 1 route
//#access Private
var jsonParser = bodyParser.json();
router.post('/', [jsonParser, auth], async (req, res) => {
const { answers } = req.body;
try {
let newTest = new algebra1({
answers: answers,
user: req.user.id,
date: Date.now()
})
console.log("body is " + req.body)
await newTest.save();
res.json({ answers: answers });
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
}
})
module.exports = router;
Algebra1.js (model for Mongoose):
const mongoose = require('mongoose');
const Algebra1Schema = new mongoose.Schema({
answers: {
type: String
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
date: {
type: Date,
default: Date.now
}
})
module.exports = algebra1 = mongoose.model('algebra1', Algebra1Schema)
submit action (submits results to api/algebra1 route):
export const submit = (results) => async dispatch => {
try {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
console.log(results);
const body = JSON.stringify({ results });
const res = await axios.post('/api/algebra1', body, config);
dispatch({
type: QuestionActionTypes.RESET
})
dispatch(setAlert('You\;ve finished your assessment!', 'success'));
} catch (err) {
console.error(err.message);
}
}

You are sending data with results key and destructing as answer key. Where are you sending anything against answer key ? I guess you meant to submit results as answers.
const body = JSON.stringify({ answers: results });

Related

Vue 3 / Express params returning their name

First off let me say sorry if the title of the question confused anyone reading my question. I didn't know how to best word my question. The issue I'm having is when I try to send a get request from my axios instance to my express instance. When I send data from axios, I have my object showing all the data it needs but when I try to utilize that data in express using req.params.email the value its holding is :email heres my code:
Client/Axios
checkEmail (data) {
return http.get('/users/:email', data)
},
Value of 'data' Object
{email: 'ThisIs#MyEmail.Org'}
Server/Express
router.get('/users/:email', function (req, res) {
console.log(req.params.email)
const data = User.find({ email: req.params.email })
return res.sendStatus(200).json(data)
})
Server Console Log
{ email: ':email' }
As a side note I have tried to just use req.params but it returns the same thing. If anyone can point out what I'm doing wrong I would greatly appreciate it!
This code will works.
You needs to switch from hard code data
to your const data = User.find({ email: req.params.email })
From
const data = {
email: 'test#gmail.com',
first_name: 'Tom',
last_name: 'Cruise'
}
To
const data = User.find({ email: req.params.email })
server.js
const express = require("express")
const axios = require('axios')
const cors = require("cors")
const app = express()
app.use(cors())
app.get("/users/:email", async (req, res) => {
console.log("params", req.params);
// const data = User.find({ email: req.params.email })
const data = {
email: 'test#gmail.com',
first_name: 'Tom',
last_name: 'Cruise'
}
res.status(200).json(data);
});
app.listen(3000, () => { console.log("Listening on :3000") })
client.js
const axios = require('axios')
const checkEmail = async (data) => {
try {
const response = await axios.get(`http://localhost:3000/users/${data}`);
return Promise.resolve(response.data)
} catch (error) {
return Promise.reject(error)
}
};
checkEmail('ThisIs#MyEmail.Org')
.then(result => {
console.log('user is : ' + JSON.stringify(result))
})
.catch(error => {
console.log(error.message)
});
Install dependencies
npm install express axios cors
Run first server
node server.js
Run second client
node client.js
Result at server
Result at client

How to create multiple collections and send posts dynamically in mongodb / mongoose

Basically I am trying to make a to-do-app which will be based on the CITY that a user submits from, if they submit from VANCOUVER, then I want there to be a collection created named VANCOUVER and the post to be submitted there, then I can collect posts from that collection, the reason being performance when I begin to add query , so I dont have to query alot of the posts if I just need info from 1 city.
I did read the docs and current I am experimenting, would love some input here.
If someone can point me to some articales or guides / good doc points, I would love that or just help me if I am going the right way , or perhaps I should be looking at the problem in a different light?
This is my current route file
const express = require('express');
const router = express.Router();
// Schema import
const postModel = require('../models/postModel');
const vancouver = require('../models/cityModel');
const toronto = require('../models/cityModel');
const victoria = require('../models/cityModel');
const mongoose = require('mongoose');
// this should return all of the posts inside of a single city
// wildcard could be vancouver or toronto for example
router.get('/:wildcard', (req, res, next) => {
req.params.wildcard.find((error, returnedDocuments) => {
if (error) return next(error);
res.json(returnedDocuments);
});
});
// this should delete a single post, via an ID identification , inside of a specific city
// the city will be set on the user side
router.delete('/:wildcard', (req, res, next) => {
req.params.wildcard.findByIdAndRemove(req.query.postid, (error, returnedDocuments) => {
if (error) return next(error);
res.json(returnedDocuments);
});
});
router.post('/:wildcard', (req, res, next) => {
req.body.wildcard.create({ post: req.body.post }, (error, returnedDocuments) => {
if (error) {
throw new Error(error);
}
});
});
module.exports = router;
the city mode is basically just the city name, and has an array for posts, these will be queried based on the category that the user wants to access
const citySchema = new mongoose.Schema(
{
name: { type: String },
posts: { type: Array }
},
{
timestamps: true
}
);
module.exports = mongoose.model('city', citySchema);
You can parameterize the model-generation:
const express = require('express');
const router = express.Router();
// Schema import
const postModel = require('../models/postModel');
const citySchema = require('../models/citySchema');
const mongoose = require('mongoose');
const getModel = (name) => mongoose.modelNames().contains(name) ? mongoose.model(name, citySchema) : mongoose.model(name)
router.get('/:wildcard', (req, res, next) => {
// You should add some validation on the wildcard before using it directly here
getModel(req.params.wildcard).find((error, returnedDocuments) => {
if (error) return next(error);
res.json(returnedDocuments);
});
});
// ...
module.exports = router;
citySchema:
const citySchema = new mongoose.Schema(
{
name: { type: String },
posts: { type: Array }
},
{
timestamps: true
}
);
module.exports = citySchema;
A thing to note is that you are risking creating arbitrarily many models and collections, which might have some performance impact as well.

axios get request to mongodb returns empty data

I make an axios request from the frontend through node to a Mongodb database requesting a userName based on userId. The request comes back as having been made, but no data is returned.
This is the Mongodb users collection:
{
"_id" : ObjectId("5e1b46cb2e6f4c98904598b0"),
"userId" : "foo#baz.com",
"userName" : "Fool",
}
This is the 'Users' schema file
users model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
userId: String,
userName: String,
});
module.exports = mongoose.model('Users', UserSchema);
This is the backend request:
backend:
const express = require('express');
const UserRoute = express.Router();
const Users = require('../Models/UserModel');
UserRoute.route('/fetchUserName').get(function (req, res) {
Users.find({userId: req.query.userId}, {userName: 1})
.exec(function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
console.log(user.data);
res.json(user.data);
}
});
});
Here is the actual request from the frontend:
getUserName = () =>
axios.get('http://localhost:4000/Users/fetchUserName', {params: {userId: 'foo#baz.com'}})
.then(res => {
return res.data;
});
};
res.data is returned as an empty string.
Any ideas why the request does not work.
The userId should probably send as a string.
So either:
const params {
userId: 'foo#baz.com'
}
axios.get('http://localhost:4000/Users/fetchUserName', { params })
or
axios.get('http://localhost:4000/Users/fetchUserName', {params: {userId: 'foo#baz.com'}})

Can't get a response from my server. Why?

I can't get a response from my server. I am using postman and running the following post request:
localhost:4000/users/register?email=test#gmail.com&f_name=testf&s_name=tests&password=test
It hangs for a very long time and then says:
Could not get any response
This is my code:
[user.route.js]
const express = require('express');
const userRoutes = express.Router();
const cors = require('cors');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
//require User model in the routes module
let User = require('../models/user.model.js');
//Make router use cors to avoid cross origin errors
userRoutes.use(cors);
//secret
process.env.SECRET_KEY = 'secret';
//define register route
userRoutes.post('/register', (req, res) => {
const today = new Date();
const userData = {
email: req.body.email,
f_name: req.body.f_name,
s_name: req.body.s_name,
password: req.body.password,
created: today
}
//Find one user based on email, hash their password and then create a document in the collection for that user
User.findOne({
email: req.body.email
})
.then(user => {
if (!user) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
user.password = hash;
User.create(userData)
.then(user => {
res.json({
status: user.email + ' registered'
});
})
.catch(err => {
res.send('error: ' + err);
});
});
}
});
});
userRoutes.post('/login', (req, res) => {
User.findOne({
email: req.body.email
})
.then(user => {
if (user) {
if (bcrypt.compareSync(req.body.password, user.password)) {
const payload = {
_id: user._id,
f_name: user.f_name,
s_name: user.s_name,
email: user.email
}
let token = jwt.sign(payload, process.env.SECRET_KEY, {
expiresIn: 1440
});
res.send(token);
} else {
res.json({
'Error': 'Password Incorrect'
});
}
} else {
res.json({
'Error': 'User does not exist'
});
}
})
.catch(err => {
res.send('Error: ' + err);
});
});
module.exports = userRoutes;
[user.model.js]
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let User = new Schema({
email: {
type: String
},
f_name: {
type: String
},
s_name: {
type: String
},
password: {
type: String
},
created: {
type: String
}
}, {
collection: 'users'
});
[server.js]
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const PORT = 4000;
const cors = require('cors');
const mongoose = require('mongoose');
const config = require('./db.js');
mongoose.Promise = global.Promise;
mongoose.connect(config.DB, {
useNewUrlParser: true
}).then(
() => {
console.log('Database is connected')
},
err => {
console.log('Can not connect to the database' + err)
}
);
app.use(cors());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
var Users = require('./routes/user.route');
//make /users use routes
app.use('/users', Users);
app.listen(PORT, function() {
console.log('Server is running on Port:', PORT);
});
[db.js]
module.exports = {
DB: 'mongodb://localhost:27017/pharaohcrud'
}
I'm using Node, MongoDB, Mongoose, Vue, Express.
I'm new to Node in general so it's hard for me to give details on what i've done. Please feel free to ask any questions that you need answered to help me with issue and ill answer as thoroughly as i can :)
EDITS:
Here is the updated db.js file
module.exports = {
DB: 'mongodb://localhost:27017/pharaoh'
}
Here is the updated post request that im sending to the server through postman:
localhost:4000/users/register
[raw json request]
{
"email": "test#gmail.com",
"f_name": "test",
"s_name": "test",
"password": "test"
}
You have to send json data with your post request not query strings.
In postman, select "Body" tab and choose "raw" and from the dropdown menu select "json" format. Send your user data as Json, this will solve the issue.
Image description here
I went deleted all database-related code and retyped it, and now it works. I guess the lesson here is to always pay attention while typing code to make sure you're writing it correctly.

consuming a rest api inside Express: userid not found

Insprirated on Gettin MEAN I am making my own application. I try to connect to front end to the backend in Express. I copied the text but my console.log still giving me the message 'userid not found'. I think I am pretty close to the finish. Any tips or helpful links are appreciated.
the Usermodel
const userSchema = new Schema({
firstName: String,
lastName: String,
userName: String,
telephone: String,
password: String
});
2. the route in the api
router
.route('/users/:userid')
.get(ctrlUsers.userReadOne);
module.exports = router;
In Postman this get.request works (for example)
http://localhost:3000/api/users/5ad87da47bb05b0594fff5b6
Together with the book I programmed the app/server/controller:
route:
const express = require('express');
const router = express.Router();
const ctrlUsers = require('../controllers/users');
router.get('/users/:userid', ctrlUsers.userInfo);
module.exports = router;
and the controllers. Here my console.log gives 'no userid found'
const request = require('request');
const apiOptions = {
server: 'http://localhost:3000'
};
if (process.env.NODE_ENV === 'production') {
apiOptions.server = 'https://pure-temple-67771.herokuapp.com';
}
/*Get myprofile */
const userInfo = function (req, res) {
const path = '/api/users/${req.params.userid}';
requestOptions = {
url: apiOptions.server + path,
method: 'GET',
json: {}
};
console.log('path ' + requestOptions.url);
request(
requestOptions,
(err, response, body) => {
_rendermyProfile(req, res, body);
console.log(body); // no userid found
});
};
const _rendermyProfile = function (req, res, userDetail) {
res.render('myProfile', {
profile: {
title: 'Mijn profiel',
firstName: userDetail.firstName,
lastName: userDetail.lastName,
email: userDetail.email,
telephone: userDetail.telephone
}
});
};
module.exports = {
userInfo
};
Of course you will get no userid found, because you have a misusage of string literal. Inside your controller, changed from this:
const path = '/api/users/${req.params.userid}';
to this:
const path = `/api/users/${req.params.userid}`;
String literal is only working if you used a back slash `.
Now your App should make a request correctly.

Resources