ReactJS - JavaScript: Failing to dynamically pass API data to MongoDB database - javascript

I am building a small boat visualizer using AIS APIs. After inquiring the APIs I am able to obtain a json file with the vessels and filter with only the vessel I am interested in, and inject them into a table on the webpage. The API gives several fileds but I only filter specific ones: [NAME, CALLSIGN, HEADING, SOG, IMO, MMSI, LONGITUDE, LATITUDE, DATE]. I can correctly connect to MongoDB as I sudo npm start.
Please shed light on why information are not being saved. I followed the documentation and a lot of posts but still something is not right.
The problem: I would like to send also the API data to a collection to MongoDB database. I successfully connect to MongoDB but information are not being passed. I don't understand why that is happening despite following official documentation on forming a Schema is followed.
Below is how I try to write to MongoDB:
users.js
var express = require('express');
var router = express.Router();
const LatitudeLongitude = require('../models/LatitudeLongitude');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.post('/vessles/map/latlng', function(req, res) {
const { name, callsign, heading, sog, imo, mmsi, longitude, latitude, date } = req.body;
let errors = [];
// Check required fields
if (!name || !callsign || !heading || !sog || !imo || !mmsi || !longitude || !latitude || !date) {
errors.push({ msg: 'No data received' });
console.log('error');
}
// vessel exists
const newVessel = new LatitudeLongitude({
name,
callsign,
heading,
sog,
imo,
mmsi,
longitude,
latitude,
date
});
// Save all vessels info
newVessel.save(function(err, vessel) {
if (err) return console.log(err);
});
res.status(200).end();
});
LatitudeLongitude.js --> forming a Schema
const mongoose = require('mongoose');
const LatitudeLongitudeSchema = new mongoose.Schema(
{
name: {
type: String,
required: true
},
callsign: {
type: String,
required: true
},
heading: {
type: Number,
required: false
},
sog: {
type: Number,
required: true
},
imo: {
type: Number,
required: false
},
mmsi: {
type: Number,
required: false
},
longitude: {
type: Number,
required: false
},
latitude: {
type: Number,
required: false
},
date: {
type: Date,
required: true
}
},
{ collection: 'latitudelongitude' }
);
const LatitudeLongitude = mongoose.model('LatitudeLongitude', LatitudeLongitudeSchema);
module.exports = LatitudeLongitude;
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('./config/keys');
var app = express();
app.use(cors());
app.options('*', cors());
// DB Config
const db = require('./config/keys').MongoURI;
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
poolSize: 10
};
mongoose
.connect(db, options)
.then(() => console.log('MongoDB Connection established'))
.catch((err) => console.log('Error connecting MongoDB database due to: ', err));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Bodyparser
app.use(express.urlencoded({ extended: false }));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
const PORT = process.env.PORT || 3000;
app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(cors());
app.listen(PORT, console.log(`Server started on port ${PORT}`));
module.exports = app;
Also below is my collection for completeness:
what I have done so far:
I tried many different ways to pass data from the API to MongoDB and the best approach I found simple is the one above I posted, but there is an error I can't seem to catch.
I believe that the file users.js should be the one that is probably missing something.
The connection to the database happens on the file app.js and I can confirm that the I can successfully connect to MongoDB.
I consulted this source, and also this one. But none of them was useful to understand what I am doing wrong.

Related

Cant connect to specific database and collection inside mongoDB Atlas Cluster

I am creating a MERN stack application and have chosen to use mongoose to communicate with MongoDB Atlas. But MongoDB Atlas uses clusters with databases inside which again has collections. I cant find any documentation for how to connect to a specific database and collection.
this is my current code:
File with the schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
User: {
fisrtname: String,
lastname: String,
email: String,
password: String,
},
Todos: [
{
title: String,
completed: Boolean,
id: Schema.Types.ObjectId,
},
],
});
module.exports = mongoose.model('User', userSchema, 'todosCollection');
Main server file
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const dbConfig = require('./database/db');
const app = express();
const PORT = process.env.PORT || 8080;
// Connecting to MongoDB database
mongoose.Promise = global.Promise;
mongoose
.connect(dbConfig.db, {
useNewUrlParser: true,
})
.then(
() => console.log('Database Sucsessfully connected!'),
err => console.error('Could not connect to database: ' + err)
);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.use('/api/todos', require('./routes/api/todos'));
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`));
And the function who searches MongoDB
! This is a snippet from another file but the rest is unimportant to the question.
const userSchema = require('../../database/models/User');
router.get('/', (req, res) => {
userSchema.find((err, data) => {
if (err) {
res.staus(500).json({ msg: 'Did not found database data' });
} else {
res.json(data);
}
});
});
Once you have connected with your Atlas MongoDB cluster - you can treat it the same as any other MongoDB connection. See my answer on how to correctly connect to an Atlas cluster: https://stackoverflow.com/a/61480485/8322220.
However, you also seem to be having an issue querying your data, but it is hard to help without the relevant code.
However, in your 3rd snippet, you are querying User - but I think your User schema is not correct.
I suggest that you separate Todos into its own Schema and export separately to User i.e:
module.exports = mongoose.model('Todo', todoSchema)
By passing dbname as options parameter you can specify the database,
check out the link for clarity.
https://mongoosejs.com/docs/connections.html#options

Error connection MongoDB: Error: Route.get() requires a callback function but got a [object Undefined]

I have been trying to connect my application to MongoDB using express but without success. Below the most important part of the code:
app.js:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var mongoose = require('mongoose');
const bodyParser = require('body-parser');
const vesselController = require('./controllers/VesselController');
require('./config/keys');
var app = express();
app.use(cors());
app.options('*', cors());
// DB Config
const db = require('./config/keys').MongoURI;
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
poolSize: 10
};
mongoose
.connect(db, options)
.then(() => console.log('MongoDB Connection established'))
.catch((err) => console.log('Error connecting MongoDB database due to: ', err));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Bodyparser
app.use(express.urlencoded({ extended: false }));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const PORT = process.env.PORT || 3000;
app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(cors());
app.route('/vessels/all').get(vesselController.getBaseAll);
app.route('vessels/:id/track').get(vesselController.getCurrent);
app.route('/vessels').get(vesselController.getHistory);
app.listen(PORT, console.log(`Server started on port ${PORT}`));
module.exports = app;
VesselController.js
const Vessels = require('../models/Vessels');
const Positions = require('../models/Positions');
const Compnanies = require('../models/Companies');
exports.getBaseAll = (req, res) => {
Promise.all([
Compnanies.find(),
Vessels.find(),
Positions.aggregate([
{
$sort: {
date: -1
}
},
{
$group: {
_id: '$callsign',
details: {
$push: '$$ROOT'
}
}
},
{
$replaceRoot: {
newRoot: {
$arrayElemAt: [ '$details', 0 ]
}
}
}
])
])
.then(([ companies, vessels, positions ]) => {
// apply vessels detail table as join:
positions.forEach((pos) => {
vessels.forEach((ves) => {
if (pos.callsign == ves.callsign) {
p._detail = ves;
}
});
companies.forEach((com) => {
if (p._detail.company == com.number) {
p._detail = com;
}
});
});
res.status(200).json(positions);
})
.catch((err) => {
return res.status(500).send(err);
});
};
exports.getHistory = (req, res) => {
var id = req.param.id;
Positions.find(
{
callsign: id,
date: {
$gte: new Date(Date.now() - 1000 * 60 * 60 * 24)
}
},
(err, task) => {
if (err) {
return res.status(500).send(err);
}
res.status(200).json(task);
}
);
};
exports.getCurrent = (req, res) => {
var currentPos = Positions.find({
date: {
$gte: new Date(Date.now() - 1000 * 60 * 60)
}
});
currentPos.exec((err, task) => {
if (err) {
return res.status(500).send(err);
}
res.status(200).json(task);
});
};
I am not sure if the problem is due to the fact that I am trying to connect to a specific database. After hitting connect to my application as shown below and copy/paste the key:
mongodb+srv://<username>:<password>#vessel-tracker-cluster-x2lpw.mongodb.net/test?retryWrites=true&w=majority
Below is how my cluser is organized:
And after accessing the collections you can see how the database is structured:
What I have done to solve the problem:
Posts that I came across and analyzed to solve the problem were:
1) This was useful but I could not solve the problem.
2) I used this other source but problem still stays.
3) This one was also useful but my problem still stay and MongoDB is not properly connecting
Thanks for pointing in the right direction for solving this problem.
As I see from the stack trace there's an error in app.js:77:27:
app.route('/vessels/all').get(vesselController.getBaseAll);
Though I've executed your code and it worked fine I would like to propose you the following:
1) Try to substitute exports with module.exports in your VesselController.js;
2) Try to debug app.js and see what vesselController.getBaseAll / vesselController.getCurrent / vesselController.getHistory returns:
console.log(vesselController.getBaseAll); // should be [Function]

ReactJS - MongoDB - JavaScript: MongoDB is not receiving any data from API

I am building a boat visualizer using AISHub APIs. After inquiring the APIs I am able to obtain a json file with the vessels I am interested in and inject these vessels inside a table.
the problem I have is that after I receive and filter the data from the API, I would like to send them to MongoDB to store them. As of now MongoDB is not receiving any data and I don't know why?
According to the official documentation of MongoDB here is what I did to create the database:
After hitting connect to my application as shown below and copy/paste the key:
mongodb+srv://<username>:<password>#vessel-tracker-cluster-x2lpw.mongodb.net/test?retryWrites=true&w=majority
Below is how my cluser is organized:
And after accessing the collections you can see how the database is structured:
app.js
var app = express();
app.use(cors());
app.options('*', cors());
// DB Config
const db = require('./config/keys').MongoURI;
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
poolSize: 10
};
mongoose
.connect(db, options)
.then(() => console.log('MongoDB Connection established'))
.catch((err) => console.log('Error connecting MongoDB database due to: ', err));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Bodyparser
app.use(express.urlencoded({ extended: false }));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const PORT = process.env.PORT || 3000;
app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(cors());
app.route('/vessels/all').get(vesselController.getBaseAll);
app.route('vessels/:id/track').get(vesselController.getCurrent);
app.route('/vessels').get(vesselController.getHistory);
app.listen(PORT, console.log(`Server started on port ${PORT}`));
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
var axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();
let hitCount = 0;
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
const mmsiOfInterest = [
'367029520',
'366909730',
'367128570'
];
const shipNamesOfInterest = [
'MICHIGAN',
'JP BOISSEAU',
'DELAWARE BAY
];
router.get('/hello', async function(req, res, next) {
const cData = myCache.get('cData');
if (!cData) {
hitCount++;
console.log(`hit ${hitCount} number of times`);
const { data } = await axios.get(
'http://data.aishub.net/ws.php?username=request'
);
const [ metaData, ships ] = data;
const shipsOfInterest = ships.filter(
(ship) => mmsiOfInterest.includes(ship.MMSI) || shipNamesOfInterest.includes(ship.NAME)
);
myCache.set('cData', shipsOfInterest, 70);
res.send(data);
return;
}
res.send(cData);
});
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
// vessel models
const Vessles = require('../models/Vessels');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.post('/vessles/map', function(req, res) {
const { callsign, name, imo, mmsi } = req.body;
let errors = [];
// Check required fields
if (!callsign || !name || !imo || !mmsi) {
errors.push({ msg: 'No data received' });
}
if (
Vessles.findOne({ mmsi: mmsi }).then((vessels) => {
if (vessels) {
// vessel exists
const newVessel = new Vessles({
callsign,
name,
imo,
mmsi
});
}
})
);
});
module.exports = router;
MondoDB Schema organization for Vessels.js
const mongoose = require('mongoose');
const VesselsSchema = new mongoose.Schema({
callsign: {
type: String,
required: true
},
name: {
type: String,
required: true
},
imo: {
type: Number,
required: false
},
mmsi: {
type: Number,
required: false
}
});
const Vessels = mongoose.model('Vessels', VesselsSchema);
module.exports = Vessels;
Posts that I have been reading to help me solve the problem but without success:
1) front end react is not sending data to db
2) connection to mongo db in react
3) This source was very useful but does not quite operate what I am trying to solve as it is more for rendering. Will surely be useful later though.
4) I thought that this source was extremely useful but didn't fully and clearly explain the process, otherwise with more explanation would probably be good.
Thanks for pointing in the right direction for solving this problem.

Mongoose model - TypeError: Account is not a constructor

I'm trying to define a model in account.js and export it to my server.js file. When I try to create a new instance of the model, I get this error:
"TypeError: Account is not a constructor
It's probably simple mistake but I couldn't figure out why it's not recognizing it as a constructor.
These are my files:
account.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const accountSchema = new Schema({
fullname:{
type: String,
required: true,
},
username:{
type: String,
required: true,
unique: true,
}
}, {
collection: 'accounts',
});
mongoose.connect('mongodb://localhost/accountsdb', (error) => {
if(error) console.log(error);
console.log("Database connection successful.");
});
module.exports = mongoose.model('Account', accountSchema);
Server.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
const Account = require("account");
var app = express();
app.use(express.static('assets'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(req, res) {
res.sendFile('index.html', {root : __dirname + '/'});
});
app.post('/signup', function(req,res){
console.log(req.body);
const newAccount = new Account(req.body); //ERROR here
newAccount.save((err) => {
if(err) throw err;
res.redirect('/');
});
});
app.use(express.static(__dirname + '/'));
app.listen(3000);
console.log('Listening on port 3000');
In your server.js, your import for Account is wrong. Import like this instead:
const Account = require("./account");
The problem here is with the way you required Account. Without a "/", "./" or "../" prefixed to account in require('account'), it is trying to import a core module or one of the node_modules (if in main directory).

Getting "Internal Server Error" in my node.js app using passport.js facebook strategy

In my Node app I am using Passport.js Facebook Strategy. I have successfully deplayed my app on heroku and also have made my app public. But only if I login it works. If someone else logs in it promts Internal Server Error.
To check, I checked my mlab database but no data of the logged in user displays.
app.js
const express = require('express');
const exphbs = require('express-handlebars');
const mongoose = require('mongoose');
const passport = require('passport');
const session = require('express-session');
const methodOverride = require('method-override');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
var path = require("path");
// var path = require("path");
//jade
// const jade = require('jade');
//Load Models
require('./models/User');
require('./models/Story');
//Passport config
require('./config/passport')(passport);
//Load Routes
const index = require('./routes/index');
const auth = require('./routes/auth');
const stories = require('./routes/stories');
//Load Keys
const keys = require('./config/keys');
//handlebars helpers
const {
truncate,
stripTags,
formatDate,
select,
editIcon
} = require('./helpers/hbs');
//Load Global Promise
mongoose.Promise = global.Promise;
//Mongoose Connect
mongoose.connect(keys.mongoURI,{
useMongoClient: true,
})
.then(()=>console.log('MongoDB Connected............'))
.catch(err => console.log(err))
const app = express();
// body-parser middleware
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, '/public')));
app.engine('handlebars', exphbs({
helpers: {
truncate: truncate,
stripTags: stripTags,
formatDate: formatDate,
select: select,
editIcon: editIcon
},
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// app.use(express.static(path.join(__dirname, '/public')));
// app.set('view engine', 'jade');
//Session n cookieParser Middleware
app.use(cookieParser());
app.use(session({
secret: 'secrethaibc',
resave: true,
saveUninitialized: true,
// cookie: {secure: true} //if using https only
cookie: {maxAge: 5*60*60*1000 }, //5 hours of inactivity
rolling: true
}));
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
//method-override Middleware
app.use(methodOverride('_method'));
//Set Global vars
app.use((req,res,next) => {
res.locals.user = req.user || null;
next();
});
//Use routes
app.use('/',index);
app.use('/auth',auth);
app.use('/stories',stories);
const port = process.env.PORT || 9000; //process.env.PORT for production port
app.listen(port,()=>console.log(`Server set at ${port}`));
passport.js
const FacebookStrategy = require('passport-facebook').Strategy;
const mongoose = require('mongoose');
const keys = require('./keys');
//Load User model
const User = mongoose.model('users');
module.exports = function(passport){
//FacebookStrategy
passport.use(new FacebookStrategy({
clientID: keys.facebookAppID,
clientSecret: keys.facebookAppSecret,
callbackURL: '/auth/facebook/callback',
profileFields: ['id','displayName','photos','emails'], //did long method could have used 'name'
proxy: true //not sure about this
}, (accessToken, refreshToken, profile, done)=>{
// console.log(accessToken);
// console.log(profile);
const image = `https://graph.facebook.com/${profile.id}/picture?`;
// console.log(image);
const name = profile.displayName.split(' ');
const newUser ={
ID: profile.id,
firstName: name[0],
lastName: name[1],
// firstName: profile.displayName.value.substring(0, profile.displayName.value.indexOf(' ')),
// lastName: profile.displayName.value.substring(profile.displayName.value.indexOf(' '+ 1),),
email: profile.emails[0].value,
image: image
}
// console.log(newUser); for debugging
//Check for existing user
User.findOne({
ID: profile.id
})
.then(user => {
if(user){
//Return User
done(null,user);
}
else{
//Create User
new User(newUser)
.save()
.then(user => done(null,user));
}
})
})
);
//Serialize and Deserialize User
passport.serializeUser((user,done)=>{
done(null,user.id);
});
passport.deserializeUser((id,done)=>{
User.findById(id, (err,user)=>{
done(err,user);
});
});
}
auth.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
//Google Authentication
router.get('/google',
passport.authenticate('google',{scope: ['profile','email'] }));
router.get('/google/callback',
passport.authenticate('google',{ failureRedirect: '/'}),(req,res)=>{
// Successful authentication, redirect home.
res.redirect('/dashboard')
});
//Facebook Authentication
router.get('/facebook',
passport.authenticate('facebook'));
router.get('/facebook/callback',
passport.authenticate('facebook',{failureRedirect:'/'}),(req,res)=>{
// Successful authentication, redirect home.
res.redirect('/dashboard');
});
router.get('/verify',(req,res)=>{
if(req.user){
console.log(req.user);
} else {
console.log('!!!!!!!! Not Auth !!!!!!!!!');
}
});
router.get('/logout',(req,res)=>{
req.logout();
res.redirect('/');
});
module.exports = router;
If you want to try login: App URL

Categories

Resources