I am beginner studying node.js, REST API and MongoDB by following some online resources. I tried to use the keyword "require" in my following code so that the users are not allowed to input blank value:
ninjas.js (create schema and models)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//create Schema and model
const NinjaSchema = new Schema({
name:{
type: String,
require: [true,'Name field is required']
},
rank:{
type: String,
require: [true,'This field is required']
},
available:{
type: Boolean,
default: false,
require: [true,'This field is required']
}
//add in geo loction
});
const Ninja = mongoose.model('hi ninja',NinjaSchema);
module.exports = Ninja;
Below is the code handling the API:
api.js
const express = require('express');
const Ninja = require('../models/ninjas');
const router = express.Router();
//get a list of ninjas from the database
router.get('/ninjas',(req,res,next)=>{
res.send({type: 'GET'});
})
//add a new ninjas to the database
router.post('/ninjas',(req,res,next)=>{
//create a Ninja object and save it to DB
Ninja.create(req.body).then((ninja) => {
res.send(ninja)
}).catch(next);
})
//update a ninjas in the database
router.put('/ninjas/:id',(req,res,next)=>{
res.send({type: 'PUT'});
})
//delete a ninjas from the database
router.delete('/ninjas/:id',(req,res,next)=>{
res.send({type: 'DELETE'});
})
module.exports = router;
Below is the main program:
index.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
//set up express app
const app = express();
//connect to mondodb
mongoose.connect("mongodb://localhost/ninjago",{
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.Promise = global.Promise;
//body parser middleware
app.use(bodyParser.json());
//initialize routes
app.use('/api',require('./routes/api'));
//error handling middleware
app.use((err,req,res,next) => {
//console.log(err);
res.status(422).send({error: err.message});
});
//listen for requests
app.listen(process.env.port || 4000,() => {
console.log('now listening for requests');
});
However, when I tried to use POSTMAN to test the API, I found that even I did not some parameter, the system would still return a successful message.
May I know if there is something wrong or missing in my code causing the "require" keyword not working? Thank you so much!
Hon
Replace require with the keyword required in your schema
const NinjaSchema = new Schema({
name:{
type: String,
required: [true,'Name field is required']
},
rank:{
type: String,
required: [true,'This field is required']
},
available:{
type: Boolean,
default: false,
required: [true,'This field is required']
}
//add in geo loction
});
See this for reference.
Related
I recently developed a react app with nodejs which depends on mongodb for its data. I have also just installed mongodb on Google Compute Engine and opened port 27017. However, my question is, how can i connect my application (I am using Mongoose) to the VM Instance.
Here is the connection string on localhost (my local machine), what should I change it to:
module.exports = {
url: 'mongodb://localhost:27017/dapashirts'
}
Here is my server.js file:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require("cors");
const app = express();
app.use(cors());
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
// Configuring the database
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
// Connecting to the database
mongoose.connect(dbConfig.url, {
useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true
}).then(() => {
console.log("Successfully connected to the database");
}).catch(err => {
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
});
// Require routes
require('./routes/department.routes.js')(app);
require('./routes/category.routes.js')(app);
require('./routes/product.routes.js')(app);
require('./routes/order.routes.js')(app);
app.listen(3500, () => {
console.log("Server is listening on port 3500");
});
Here is a sample model:
const mongoose = require('mongoose');
const ProductSchema = mongoose.Schema({
category_id: {
type: [mongoose.Schema.Types.ObjectId],
required: true
},
name: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
discounted_price: {type: Number, default: 0.00},
image: String,
image_2: String,
thumbnail: String,
display: { type: Number, min: 0, max: 3, default: 0 }
});
module.exports = mongoose.model('Product', ProductSchema);
Here is a sample route:
module.exports = (app) => {
const products = require('../controllers/product.controllers.js');
// Create a new product
app.post('/products', products.create);
// Retrieve all products
app.get('/products', products.findAll);
// Retrieve a single product with productId
app.get('/products/:productId', products.findOne);
// Retrieve a products with categoryId
app.get('/products/:categoryId', products.findWithCategoryId);
// Update a product with productId
app.put('/products/:productId', products.update);
// Delete a produt with productId
app.delete('/products/:productId', products.delete);
}
How do i also transfer my localhost database to Google Compute Engine
The easiest way is to use a database as a service (daas) from Mongo DB:
https://www.mongodb.com/cloud/atlas
I get error cannot POST /auth/auth/register with my code but when I change
app.get('/auth/register')toapp.get('/register') the code works fine. Can anyone please tell me where the problem is and it would be a great help if anyone help me in solution .
I have tried changing app.get('/auth/register') to other routes like ('/create/registration'), app.get('/Registering/user') but it doesn't work .Should I should use only app.get('/userRegister') or app.get('createNewUser') or app.get('goodRegister')
const express = require('express');
const expressEdge = require('express-edge');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const userController = require('./controllers/createUser');
const storeUserController = require('./controllers/storeUser');
const app = new express();
app.get('/auth/register', userController);
app.post('/users/register', storeUserController);
const User = require('../database/models/User')
}
//my controller
module.exports = (req, res) => {
User.create(req.body, (error, user) => {
res.redirect('/')
})
}
//my database model
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
})
UserSchema.pre('save', function(next) {
const user = this
bcrypt.hash(user.password, 10, function(error, encrypted) {
user.password = encrypted
next()
})
})
module.exports = mongoose.model('User', UserSchema);
app.listen(4000, () => {
console.log("application listening on port 4000")
})
//my view
<form action="users/register" method="POST" encType="multipart/form-data">
I have solved this problem myself. thanks to everyone for taking out time to check through and give one explanation or another.
the problem with the code is the path to my controller. the name of the file should not have been User but user so I changed const User = require('../database/models/User') to const User = require('../database/models/User') in other to match with the name of the file under the database/model directory
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".
Here is my code
file name student.js
var mongoose = require('mongoose');
var studentSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
rollno:{
type: Number,
required: true
},
grade:{
type: String,
required: true
},
result:{
type: String,
required: true
}
});
var Student = module.exports = mongoose.model('Student',studentSchema);
module.exports.getStudents = function (callback){
Student.find(callback);
}
**filename app.js**
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var PORT= process.env.PORT || 3000;
Student = require('./models/student');
mongoose.connect('mongodb://localhost/register');
var db= mongoose.connection;
app.get('/api/student', function (req,res){
Student.getStudents(function (err, student){
if(err){
throw err;
}
res.json(student);
});
});
app.listen(PORT);
console.log('Running app on port:' + PORT);
If you have an existing collection that you want to query using Mongoose, you should pass the name of that collection to the schema explicitly:
var studentSchema = new mongoose.Schema({ ... }, { collection : 'student' });
If you don't, Mongoose will generate a collection name for you, by lowercasing and pluralizing the model name (so documents for the model Student will be stored in the collection called students; notice the trailing -s).
More documentation here.
I am trying to join two collections and being able to get the combined data. To do so using Mongoose, i am supposed to use the populate syntax to achieve that. I am receiving error that the Schema Schema hasn't been registered for 'User_Fb'. From my code, I have exported the models and required in my server.js but the error is still appearing. What have I done wrong?
feed_post.model.js
var mongoose = require('mongoose');
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var User_fb = require('../models/fb_db.model');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
var Feed_Post = conn_new_app.model('Feed_Post', feed_postSchema);
module.exports = Feed_Post;
fb_db.model.js
var mongoose = require('mongoose');
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('../models/feed_post.model');
var user_fb = new mongoose.Schema({
name: String,
location: String,
fb_id: Number
});
var User_Fb = conn_new_app.model('User_Fb', user_fb);
module.exports = User_Fb;
server.js
var express = require('express'),
mongoose = require('mongoose'),
User = require('./app/models/user.model'),
Post = require('./app/models/post.model'),
Maptest = require('./app/models/maptest.model'),
Feed_Post = require('./app/models/feed_post.model'),
User_Fb = require('./app/models/fb_db.model'),
app = express();
app.get('/testget', function(req,res){
Feed_Post.findOne().populate('user_id').exec(function(err, c) {
if (err) { return console.log(err); }
console.log(c.fk_user.userName);
});
});
UPDATED from Pier-Luc Gendreau Answer's
fb_db.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var user_fb = new mongoose.Schema({
name: String,
location: String,
fb_id: Number
});
return connection.model('User_FB', user_fb);;
}
feed_post.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
return connection.model('Feed_Post', feed_postSchema);;
}
server.js
var express = require('express'),
app = express(),
mongoose = require('mongoose'),
conn_new_app = mongoose.createConnection('mongodb://localhost/new_app'),
User_Fb = require('./app/models/fb_db.model')(conn_new_app),
Feed_Post = require('./app/models/feed_post.model')(conn_new_app);
app.get('/testget', function(req,res){
Feed_Post.find().populate('user_id').exec(function(err, res) {
if (err) { return console.log(err); }
console.log(res);
});
});
This is all I had to do Customer.findOne({}).populate({ path: 'created_by', model: User }) instead of this Category.findOne({}).populate({'author'})
IF YOU (really) USE MULTIPLE mongoDB CONNECTIONS
I do realise that this is not the case for the OP, but if you genuinely use multiple connections you MUST provide the model when using .populate(), as mongoose will only "find" models on the same connection.
ie where:
var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
"name": String,
"email": String
});
var customerSchema = mongoose.Schema({
"name" : { type: String },
"email" : [ String ],
"created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});
var User = db1.model('users', userSchema);
var Customer = db2.model('customers', customerSchema);
Correct:
Customer.findOne({}).populate('created_by', 'name email', User)
or
Customer.findOne({}).populate({ path: 'created_by', model: User })
Incorrect (produces "schema hasn't been registered for model" error):
Customer.findOne({}).populate('created_by');
The problem is that you are creating a new connection in each and every model, so you end up with a bunch of different connection objects. Even though they are pointing to the same database, mongoose models don't know about other connections. You should instead create the connection object in your main app and then pass it around.
server.js
var express = require('express');
var mongoose = require('mongoose');
var app = express();
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('./app/models/feed_post.model')(conn_new_app);
app.get('/testget', function(req,res){
Feed_Post.findOne().populate('user_id').exec(function(err, c) {
if (err) { return console.log(err); }
console.log(c.fk_user.userName);
});
});
Then modify your models so they are actually a function:
feed_post.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
return connection.model('Feed_Post', feed_postSchema);;
}
Also, like Adrian mentions, you can use mongoose as a singleton. However, I do recommend using createConnection as you did because if you ever need a second connection, you won't have to refactor the connection code to your first database.
It looks like you are creating a different database connection for each model, which isolates the models from each other. Mongoose must assume this isolation, because they could exist on different databases or even database servers.
Try connecting once, and just calling mongoose.model() instead of connection.model() when defining your models. Mongoose is a singleton by default.
In my case, this issue because I haven't included the ref model into the application.
You can get the field you want by using select
Example to get the email of the customer:
Customer.findOne({}).populate({ path: 'created_by', model: User, select: 'email' })
More Details in mongoose documentation