I want to preface this by saying I have read several posts here regarding this issue.
I have a node/express/mongo app with the following:
app.js:
var express = require('express')
var bodyParser = require('body-parser')
var cors = require('cors')
var morgan = require('morgan')
var mongoose = require('mongoose')
var passport = require('passport')
var app = express()
// MongoDB Setup
var configDB = require('./config/database.js')
mongoose.connect(configDB.url)
app.use(morgan('combined'))
app.use(bodyParser.json())
// Check security with this
app.use(cors())
// load our routes and pass in our app and fully configured passport
require('./routes')(app)
app.listen(process.env.PORT || 8081)
console.log('We are up and running, captain.')
routes.js
const AuthenticationController = require('./controllers/AuthenticationController')
module.exports = (app) => {
app.post('/register', AuthenticationController.register)
}
My mongo schema file Account.js:
const mongoose = require('mongoose')
const bcrypt = require('bcrypt-nodejs')
const Schema = mongoose.Schema
var accountSchema = new Schema({
email: String,
password: String,
likesPerDay: { type: Number, min: 0, max: 250 },
followPerDay: { type: Number, min: 0, max: 250 },
unfollowPerDay: { type: Number, min: 0, max: 250 },
commentsPerDay: { type: Number, min: 0, max: 250 },
comment: String,
hashtags: [String]
})
// methods ======================
// generating a hash. We hash password within user model, before it saves to DB.
accountSchema.methods.generateHash = function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null)
}
// checking if password is valid
accountSchema.methods.validPassword = function (password) {
return bcrypt.compareSync(password, this.local.password)
}
// create the model for users and expose it to our app
module.exports = mongoose.model('Account', accountSchema)
And finally my controller file AuthenticationController.js
const Account = require('../models/Account.js')
// var bodyParser = require('body-parser')
module.exports = {
register (req, res) {
Account.findOne({email: req.body.id}, function (err, account) {
if (err) {
console.log('Could not regster user')
throw err
}
if (account) {
console.log('account already exists')
} else {
Account.insertOne({email: req.body.email, password: req.body.password}, function (err, res) {
if (err) {
console.log('could not insert')
throw err
}
console.log('inserted account')
Account.close()
})
}
})
}
}
I am getting an error in my AuthenticationController file when I call Account.insertOne function.
I get the error that
TypeError: Account.insertOne is not a function
Now several of the posts here on stack have advised that I make sure that I am exporting the model from my model class, which I am doing, and that would fix this issue. Its weird because the findOne method seems to be fine, but when I call the insertOne i get an issue.
Am I missing something here?
A Mongoose model doesn't have an insertOne method. Use the create method instead:
Account.create({email: req.body.email, password: req.body.password}, function (err, doc) {
The Mongoose docs show how to create documents:
Either via Account.create():
Account.create({email: req.body.email, password: req.body.password}, function (err, res) {
// ...
})
Or by instantiating and save()ing the account:
new Account({email: req.body.email, password: req.body.password}).save(function (err, res) {
// ...
})
edit
as of mongoose documentation, try using
Account.create({ ...params ... }, function (err, small) {
if (err) return handleError(err);
// saved!
})
insertOne command is not available in mongoose directly as mentioned in Mongoose Documentation. If you want to use insertOne command then you need to use bulk command in order to send this command to MongoDB server. Something like below. I hope this works.
Account.bulkWrite([
{
insertOne: {
document: {email: req.body.email, password: req.body.password}
}
}
}]
Related
for exemple I have a user model like this
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
username: {
type: String,
required: true,
},
Points: {
type: Number,
default: 0,
},
module.exports = User = mongoose.model("users", UserSchema);
then I want to execute a function automatically when user.points is equal to 10 with express js, is there any solution ?
#Yessine, may you should try something like this. You can add checkForPoints wherever you are updating the Points and proceed with your things,
const { Users } = require('/schema.js');
const checkForPoints = async (username) => {
await Users.findOne({ username }, function (err, data) {
if (err) {
console.log("enter error ------", err)
}
if (data && data.Points === 10) {
// Execute your code
}
});
};
// Users schema(schema.js)
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('your db', { useNewUrlParser: true });
const requestSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId,
username: String,
Points: Number
});
module.exports = mongoose.model('users', requestSchema);
Polling is a technique where we check for fresh data over a given interval by periodically making API requests to a server.enables you to periodically check for the newest values of data and do further requests once it enters the desired state.
$.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!
I am wondering if anyone can help me out here. I'm currently taking a Udemy course on learning how to connect a database with my server. I have been going word by word on the teacher's code, frequently checking if my code has any minor errors. I didn't have any trouble with code thus far on my server.js file. Port is running smoothly. However, when I run the POST request from Postman, I get
Unhandled rejection Error: Connection terminated unexpectedly
Through Postman, I am following exactly what the teacher did. The POST request contains email, password, name and the localhost:3000/register path is fine. That is what my server is connected to. I'm wondering what's going on since my code runs smoothly until I do a POST request. Also noting that I get 200 OK response on Postman but on server, I get that unhandled rejection error message.
Yeah that console log is intentional, I am going along exactly what he is doing in the video so code is bound to change over time on the next video.
const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require ('bcrypt-nodejs');
const cors = require('cors');
const knex = require('knex');
const pg = require('pg');
const db = knex({
client: 'pg',
connection: {
host : '127.0.0.1',
user : 'postgres',
port: '3000',
password : '',
database : 'smart-brain'
}
});
const app = express();
const database = {
users: [
{
id: '123',
name: 'Jess',
email: 'jess#gmail.com',
password: 'cookies',
entries: 0,
joined: new Date()
},
{
id: '124',
name: 'Sally',
email: 'sally#gmail.com',
password: 'bananas',
entries: 0,
joined: new Date()
}
]
}
app.use(bodyParser.json());
//body parser is basically json.parse. we want to always parse json so our code is readable in string form. POST > Raw > JSON
app.use(cors())
app.get('/', (req, res)=> {
res.send(database.users);
})
app.post('/signin', (req, res) => {
if(req.body.email === database.users[0].email && req.body.password === database.users[0].password) {
res.json(database.users[0])
} else {
res.status(400).json('error logging in')
}
})
app.post('/register', (req, res) => {
const { email, name, password } = req.body;
db('users').insert({
email: email,
name: name,
joined: new Date()
}).then(() => console.log())
res.json(database.users[database.users.length-1])
});
app.get('/profile/:id', (req, res) => {
const { id } = req.params;
let found = false;
database.users.forEach(user => {
if (user.id === id) {
found = true;
return res.json(user);
}
})
if (!found) {
res.status(400).json('not found...')
}
})
//now we are creating route for entries count. everytime they submit image, they will get a count for it
app.put('/image', (req, res) => {
const { id } = req.body;
let found = false;
database.users.forEach(user => {
if (user.id === id) {
found = true;
user.entries++
return res.json(user.entries);
}
})
if (!found) {
res.status(400).json('not found...')
}
})
app.listen(3000, ()=> {
console.log('app is running on port 3000');
})
try to add catch function after then block.
app.post('/register', (req, res) => {
const { email, name, password } = req.body;
db('users').insert({
email: email,
name: name,
joined: new Date()
}).then(() => {
res.json(database.users[database.users.length-1])
}).catch((err)=>{console.log(err)})
});
What I'm trying to do:
I have a small Node app makes a request to an API to get data about the stock market and then saves the data to a Mongo DB (already made and working), which I would like to run constantly. Next I need to build an API which allows my other servers/apps to get that data being (not made yet).
I think Express is a good choice although I know there are other options. I am getting this code from another API that I built for a MEAN stack app and have been looking around to troubleshoot.
My main issue is that most tutorials show how to just build a CRUD API for the MEAN, MERN, and other stacks. I'm not really sure how to structure this system or Node apps can run independently of one another in the way that I am describing.
Currently I am not getting any errors when I run the app but I am not able to get anything when I go to my endpoints.
When I first started I thought that the standalone Node app (request and writing data part of this) could live within the same file as the Express part, but now I don't think that would work and have split those into separate files. I have seen PM2 and other ways of making the node app into a background service?
Not totally sure, some clarification on that, as well as some help with why my express API endpoints won't respond with data from the database. Here is my code.
Standalone app:
const request = require('request');
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const d = new Date();
let day = d.getDay()
let hour = d.getHours();
const stockMomentSchema = new Schema({
symbol: String,
price: Number,
size: Number,
time: {type: Date, default: Date.now}
});
const StockMoment = mongoose.model('stockMoment', stockMomentSchema, 'stockPriceData');
mongoose.connect('mongodb://localhost:27017/stock-test')
.then(() => {
console.log('connected');
})
.catch(err => {
console.error(err);
});
function makeRequest() {
if(day <= 1 || day >= 5) {
if(hour >= 10 || hour <= 15) {
getMarketData();
}
}
}
function getMarketData() {
request({
url: 'https://api.iextrading.com/1.0/tops/last',
json: true
}, (err, res, body) => {
if(err) {
return console.error(err);
}
for(let i = 0; i < body.length; i++) {
const stockMoment = new StockMoment({
symbol: body[i].symbol,
price: body[i].price,
size: body[i].size,
time: body[i].time,
});
stockMoment.save((err) => {
if(err) return handleError(err);
console.log('Saved!', i);
});
console.log(body[i]);
}
});
}
makeRequest();
//setInterval(makeRequest, 5000);
server.js:
const express = require('express');
const path = require('path'); // Not sure if this is needed
const http = require('http');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
const api = require('./api');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cors());
//app.use(express.static(path.join(__dirname, 'dist'))); // Not sure if this is needed
app.use('/api', api);
app.get('*', function(req, res) {
res.status(404);
});
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
server.listen('3000', function() {
console.log('--------------------');
console.log('Server running');
console.log('You can view the server at http://localhost:3000');
console.log('If you are running an Angular app on while using this server please use http://localhost:4200');
console.log('--------------------');
});
stock model:
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const StockSchema = mongoose.Schema({
username: { type: String, unique: true, required: true },
password: { type: String, required: true },
email: {type: String, required: true},
phoneNumber: {type: String, required: true},
company: {type: String, required: true},
about: {type: String, required: true},
userType: {type: String, required: true}
});
StockSchema.plugin(uniqueValidator);
module.exports = mongoose.model('Stock', StockSchema);
api.js:
const express = require('express');
const router = express.Router();
const Stock = require('./stock.js');
router.get('/', function(req, res, err) {
console.log('Hello world');
});
router.get('/stocks/:id', function(req, res, err) {
console.log('Hello world');
const stockData = {
_id: false,
symbol: true,
price: true,
size: true,
time: true
}
Stock.findById(req.params.id, stockData, function(err, stock) {
if(err) {
res.send('No stocks found');
console.log(err);
} else {
res.json(stock);
}
});
});
module.exports = router;
Edit:
Added mongoose.connect to server.js but it still doesn't work
mongoose.connect('mongodb://localhost:27017/stock-test')
.then((res) => {
console.log('connected');
})
.catch(err => {
console.error(err);
});
Edit: Here's a gist with the working changes https://gist.github.com/drGrove/3e6699ded09f282e528a661fb41439e1
Your api is pulling in a schema that has no information associated with it.
You should break out the StockMomentData, require it from you api.js and use that in your get request by id instead of your current stock model.
Since your mongoose connection is shared between the two "applications" you can pull that out into a db.js and just require that file on load for each project (But that can always be done at a later time).
Just note that you do need a connection in either your Model file or your api.js file so that mongoose actually connects to the mongo database
Initial Answer:
Your API server is missing a connection to Mongo via mongoose. You'll have to have a connection call just like what you have in your "standalone app".
I am using node and mongoose to build an app. And when testing, there exists a strange problem. Here is my auth.index.js(for user login).
auth.index.js:
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('../config/environment');
var User = require('../api/user/user.model');
var jwt = require('jsonwebtoken');
var auth = require('./auth.service');
var router = express.Router();
router.post('/login', function (req, res, next){
User.find({email: req.body.email}, function (err, user){
if (err) {
return next(err);
} else if (!user) {
return res.json({message: 'Invalid email.'});
} else {
if(!user.authenticate(req.body.password)){
return res.json({message: 'Invalid password.'});
};
var token = auth.signToken(user._id, user.username, user.role);
return res.json({token: token});
};
});
});
Here is the user.model.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String,
password: String,
email: {type: String, lowercase: true},
role: {type: String, default: 'user'},
provider: String,
date: String
});
UserSchema.methods = {
//check password
authenticate: function(plainText) {
return plainText === this.password;
}
};
However, in the command window, it returns that
user.authenticat is not a function.
I wanna know why, and does it mean that I cannot use the method directly or I need to invoke the method through passport ? Thanks.
I think you have misplaced your methods. It should be like this.
UserSchema.methods.authenticate: function(plainText) {
return plainText === this.password;
}
See the following link for the complete example. https://scotch.io/tutorials/using-mongoosejs-in-node-js-and-mongodb-applications