I recently move in NodeJs from PHP and developing a project in MEANJS. But i unable to use a controller method in other controller. I think that i have followed wrong pattern.
student.model.js
-----------------
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var studentSchema = new Schema({
....
....
})
student.controller.js
---------------------
var Student = require('../models/student.model');
module.exports.get = function(req, res, next) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(function(err, studentData) {
if (err)
return res.status(500).end(err.message);
res.status(200).json(studentData);
})
}
report.controller.js
---------------------
var StudentCtrl = require('../controller/student.controller');
module.exports.getStudentGrade = function(req, res, next) {
//HERE I WANT get StudentCtrl.get data then response to client
//somethings like----------------
StudentCtrl.get(req,res,next){
//get studentData here
//manipulation on studentData
res.status(200).json(myReportData);
}
//-------------------
}
Make 2 versions on student.controller.get, for example student.controller.getCallback which receives a callback which you can then use in report.controller.js
student.controller.js
---------------------
var Student = require('../models/student.model');
module.exports.get = function(req, res, next) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(function(err, studentData) {
if (err)
return res.status(500).end(err.message);
res.status(200).json(studentData);
})
}
module.exports.getCallback = function(req, callback) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(callback);
}
report.controller.js
---------------------
var StudentCtrl = require('../controller/student.controller');
module.exports.getStudentGrade = function(req, res, next) {
//HERE I WANT get StudentCtrl.get data then response to client
//somethings like----------------
StudentCtrl.getCallback(req, function(err, myReportData) {
//get studentData here
//manipulation on studentData
if (err)
return res.status(500).end(err.message);
res.status(200).json(myReportData);
});
}
MEAN Stack is a complete JavaScript framework, it is a mixed of Mango dB, Express JS, Angular JS and Node JS. here Node JS play the role of server-side programming and npm server, so if you are re-forming the framework it makes into you have to independently connect MangodB, Express JS, Angular JS to PHP. please refer the link http://meanjs.org/
Please follow these steps:
mongo
index.js
models
user.js
client.js
controllers
user.js
client.js
Now
in models put all the schemas
and in controller call relevant schemas and function like save() update etc
and in the last all the controller method access it in the index hs
Related
I'm using React Admin for the first time, and my users (coming from mongoDB) are displayed just fine. The problem occurs when I click the "edit" (or "delete") button on a specific user: it says "GET http://localhost:3002/api/users/2a1a3a61-f73b-4a01-b609-ae4bb815f59e 404 (Not Found)"
I use "http://localhost:3002/api/users" to make the GET req to mongoDB: "app.use('/api/users', require('./api/GetUsers'))" and "2a1a3a61-f73b-4a01-b609-ae4bb815f59e" is the id of the user I clicked.
I remember when I first started testing React Admin, that I was using jsonplaceholder.typicode to get data and the edit function was working as well, although, of course, would not persist on refresh.
What am I missing? Is the problem the fact that my api's (http://localhost:3002/api/users) purpose is only getting the data and not post/put also, maybe?
/api/GetUsers
const express = require('express');
const mongoose = require('mongoose');
const ContactUser = require('../DB/ContactUser');
const router = express.Router();
const getUsers = async (req, res) => {
ContactUser.find()
.exec((err, user) => {
if(err){
res.json(err);
} else {
res.setHeader('Access-Control-Expose-Headers', 'Content-Range');
res.setHeader('Content-Range', 'users 0-20/20');
res.json(user);
}
})
};
router.route('/').get(getUsers);
module.exports = router;
/DB/ContactUser
const mongoose = require('mongoose');
const contactUser = new mongoose.Schema({
name: String,
email: String,
message: String,
id: String
});
module.exports = mongoose.model('contactUser', contactUser);
You're missing a second route to retrieve not a list of users, but a single user. It will use the id in the URL to find one user. Something like:
router.get('/:id', function(req, res) {
ContactUser
.findOne({ _id: req.params.id })
.exec((err, user) => err ? res.json(err) : res.json(user));
});
I am trying to save a data in MongoDB with Mongoose with Express.JS 4 and Bluebird.
What I have done is like this-
bin/www
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
.......
.......
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
{// successfully connected!
console.log("Successfully Connected to Mongo-DB");
});
And getting this in console-
Successfully Connected to Mongo-DB` - So, MongoDB connected successfully
models/post.js
var mongoose = require('mongoose');
var postSchema = new mongoose.Schema({
created_by: String, //should be changed to ObjectId, ref "User"
created_at: {type: Date, default: Date.now},
text: String
});
module.exports = mongoose.model('Post', postSchema);
app.js
var Post_Data = require("./models/post");
....
....
router.get('/', function(req, res, next)
{
var Post = mongoose.model("Post");
var post = new Post({
created_by: ""+Math.random()
});
console.log( Post.create(post) );
res.render(
'index',
{
title : 'Express',
site_name : 'Our Site',
layout : 'templates/layout'
}
);
});
And after that I am getting this in console-
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined }
But, nothing is saved, a proof for that is -
I am finding this-
After using MongoBooster.
Update-
My DB config is like this-
"MONGO_URI": "mongodb://localhost:27017/express_test",
"MONGO_OPTIONS": {
"db": { "safe": true },
"name":"express_test"
}
So, can anyone please help, why it is not saving anything?
Thanks in advance for helping.
The .create() function is a shortcut for new Model and .save(). You are trying to .create an instance of Model rather than a simple Object. See Constructing documents in Mongoose's Models documentation for their quick example.
The return from a Mongoose data function is just the promise of an asynchronous task to be run in the future, logging that is largely pointless. Use .then() to wait until the promise has been resolved.
Error handling is missing from your code as well, something could be getting thrown there. Use a .catch() for promise error handling.
Post.create({ created_by: ""+Math.random() })
.then(function (result) {
console.log('Saved' result)
})
.catch(function (err) {
console.error('Oh No', err)
})
All of this can be done with callbacks (like the Mongoose docco examples) but promises, particularly bluebird promises are nicer.
I just use this syntax combination to create and save my model:
var myPage = new LandingPage({
user:req.user,
slug: req.body.slug,
}).save(function(err,savedModel){
if(!err){
console.log(savedModel);
}
});
You are calling the wrong model in your app.js module as you are importing the model as
var Post_Data = require("./models/post"); // <-- Post_Data model never used
....
....
but creating a new Post model instance in your router implementation as
var Post = mongoose.model("Post"); // <-- different model
var post = new Post({
created_by: ""+Math.random()
});
You need to call and use the correct models. So I would suggest you re-write your app.js module to use the save() method as:
var Post = require("./models/post"); // <-- import correct Post model
....
....
router.get('/', function(req, res, next) {
var post = new Post({ created_by: ""+Math.random() });
post.save().then(function(post) {
console.log(post); // <-- newly created post
res.render('index', {
title: 'Express',
site_name: 'Our Site',
layout: 'templates/layout'
});
})
.catch(function(err) {
console.error('Oopsy', err);
});
});
if you store post schema in a variable by require then can use that variable.
var Post_Data = require("./models/post");
so can use new Post_Data no need to use var Post = mongoose.model("Post"); because you have already exported this schema module.exports = mongoose.model('Post', postSchema);
you can try this one :
var Post_Data = require("./models/post");
router.get('/', function(req, res, next)
{
var post = new Post_Data({created_by: ""+Math.random()});
post.save(function(error, data) {
if(error) {
return res.status(500).send({error: 'Error occurred during create post'});
}
return res.render('index',{
title : 'Express',
site_name : 'Our Site',
layout : 'templates/layout'
});
});
});
So it's true that if you're creating a document in memory by calling new Post(values) that you will save it with post.save(cb); rather than 'Post.create(post);, but I'm thinking that the underlying issue (though this isn't easy to be certain of based on the code you're showing) is that you're connecting with the MongoDB driver, rather than mongoose itself. Yourdb` variable isn't shown to be declared in the code you posted, so I'm making it an assumption.
That said, if I'm right, you need to call mongoose.connect or mongoose.createConnection in order for Mongoose to know it's connected to the db and save documents to it. You can pass an existing connection to mongoose, so if you're already doing so then I apologize for my erroneous assumption.
When i'm getting to my routes and requesting to getUSers from my mongoDB it says the User.find() is not defined. Sorry in advance if i use incorrect terminology i'm jumping in face first.
I'm assuming my routing is done incorrectly somewhere or i didn't include one file somewhere I'm hoping ya'll can help me determine if i'm either storing a file incorrectly in my structure, calling a file at the wrong time, or not initializing a variable correctly? Thanks for the help in advance.
Do i need an additional plugin to read and write to the database?
I keep getting the the following error it says usercontroller.js:20
Error: <!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>undefined is not a function</h1><h2></h2><pre>TypeError: undefined is not a function
at getUsers (c:\Users\Ravenous\kitchen\routes\user_api.js:5:10)
at c:\Users\Ravenous\kitchen\routes\user_api.js:26:3
file structure in case it helps
-bin
-node_modules-\
-user-app-\
-user.js //this is the model written with mongoose schema
-public-\
-html
-images
-javascripts-\
-userController
-userService //AngularJS factory
-stylesheets
-index.html
-routes-\
-user_api.js //with other useful routes inside.
-views //has some jade view engines that came with express-generator
-app.js
-package.JSON
I have this for the user model -- file: node_modules/user-app/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
user_name: String,
password: String,
email: String,
location: String,
date_created : {type: Date, default: Date.now}
});
var User = mongoose.model('User', UserSchema);
module.exports= {User:User};
I then import user.js file to the ./routes/user_api.js file which looks like this
user_api.js :
var User = require('./node_modules/user-app/user');
function getUsers(res){
User.find().populate('users').exec(function(err, users){
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err){
res.send(err)
}else{
console.log(users[0][0].name)
res.json(users); // return all users in JSON format
db.close();
}
})
};
module.exports = function(app) {
// api -----------------------------------------------------------
// get all users
app.get('/node_modules/user-app/user', function(req, res) {
// use mongoose to get all users in the database
getUsers(res);
});
// create user and send back all users after creation
app.post('/node_modules/user-app/user', function(req, res) {
// create a user, information comes from AJAX request from Angular
User.create({
user_name: User.user_name,
password: User.password,
email: User.email,
location: User.location,
done : false
}, function(err, todo) {
if (err){
res.send(err);
}else{
// get and return all the users after creating one
getUsers(res);
}
});
});
// delete a user
app.delete('/node_modules/user-app/user:user_id', function(req, res) {
User.remove({
_id : req.params.user_id
}, function(err, user) {
if (err)
res.send(err);
getUsers(res);
});
});
};
I'm adding this user_api route and get method to the app.js file like so
// loading some required modules above this
var app = express();
var user = require('./routes/user_api')(app);
to handle the Angular and Node connection and state sharing i'm using the following
userController.js:
(function(){
'use strict'
var userCtrl = angular.module("userController",[]);
console.log('userController init')
userCtrl.controller('UserController', ['$scope','$http','Users',function($scope,$http,Users){
$scope.users = {};
$scope.loading = true;
console.log ("user init");
Users.get()
.success(function(data){
$scope.users = data;
$scope.loading = false;
console.log(data)
})
.error(function(err){
console.log('Error: ' + err);
});
$scope.createUser = function(){
if($scope.users.user_name != false){
console.log($scope.users.user_name)
$scope.loading = true;
Users.create($scope.users)
.success(function(data){
$scope.loading=false;
$scope.users = data;
console.log(data);
})
.error(function(err){
console.log('Error: ' + err);
});
}
};
}]);
})();
Change the line where you require User to
var User = require('./node_modules/user-app/user').User;
This is because in your export statement when you define a user you have the line:
module.exports = {User:User};
So, you are exporting an object that has a User property on it.
I just start to use node.js with express and mongoose, and I have a stupid question...
Somewhere in my routes.js file, I have the following section :
// DASHBOARD SECTION, GET MY GROUPS
app.get('/dashboard', isLoggedIn, function(req, res) {
var Group = require('../app/models/group'); //adding mongoose Schema
Group.find({"groupDetails.userId" : req.user._id})
.exec(function(err, myGroups) {
if (err)
res.send(err);
var myGroups = myGroups;
//console.log("myGroups: " + myGroups); // check with "heroku logs"
res.render('dashboard.ejs', {
user : req.user,
myGroups : myGroups
});
});
});
This code works. When someone browse the dashboard page, I receive "myGroups" which is an array with all the groups for the current logged in user.
Now, here is my question :
Actually when someone browse the dashboard page, I would like to make a second query (based on the exact same pattern) to get all groups and all files for the current logged in user.
Then I will send "user", "myGroups" and "myFiles" to the dashboard page.
How can I do that ?
I tried several things with no result so far... I think I'm a little bit lost in node.js callback functions :D
Thanks a lot for your help.
You have two options here:
1) deal with callback hell (callback inside callback inside...) to retrieve 3 sets of data. This way is least elegant and efficient
2) Use a library that will do the job asynchronously and have one callback when all the data is retrieved, you can use async library which is just awesome. In this case you will have just one callback in which you can access all the data you have fetched.
Here's what you can do with async in your case:
var async = require('async');
..........
app.get('/dashboard', isLoggedIn, function(req, res) {
var Group = require('../app/models/group'); //adding mongoose Schema
var User = require('../app/models/user'); //adding mongoose Schema
var Files = require('../app/models/files'); //adding mongoose Schema
async.parallel({
groups: function(callback){
Group.find(...).exec(callback);
},
users: function(callback){
Users.find(...).exec(callback);
},
files: function(callback){
Files.find(...).exec(callback);
}
}, function(err, results) {
if (err)
res.send(err);
var groups = results.groups;
var users = results.users;
var files = results.files;
res.render('dashboard.ejs', {
user : req.user,
myGroups : groups,
users: users,
files: files
});
});
});
I see lots of examples where node.js / express router code is organized like this:
// server.js
var cats = require('cats');
app.get('/cats', cats.findAll);
// routes/cats.js
exports.findAll = function(req, res) {
// Lookup all the cats in Mongoose CatModel.
};
I'm curious if it would be okay to put the logic to create, read, update and delete cats in the mongoose CatModel as methods? So you could do something like cat.findAll(); The model might look something like this:
var Cat = new Schema({
name: {
type: String,
required: true
}
});
Cat.methods.findAll = function(callback) {
// find all cats.
callback(results);
}
Then you could use this in your router:
app.get('/cats', cats.findAll);
If if further logic / abstraction is needed (to process the results) then one could do it in routes/cats.js.
Thanks in Advance.
Obviously your architecture is completely up to you. I've found that separating my routes (which handle business logic) and models (which interact with the db) is necessary and very easy.
So I would usually have something like
app.js
var cats = require ('./routes/cats');
app.get('/api/cats', cats.getCats);
routes/cats.js
var Cats = require ('../lib/Cats');
exports.getCats = function (req, res, next) {
Cat.get (req.query, function (err, cats) {
if (err) return next (err);
return res.send ({
status: "200",
responseType: "array",
response: cats
});
});
};
lib/Cat.js
var catSchema = new Schema({
name: {
type: String,
required: true
}
});
var Cat = mongoose.model ('Cat', catSchema);
module.exports = Cat;
Cat.get = function (params, cb) {
var query = Cat.find (params);
query.exec (function (err, cats) {
if (err) return cb (err);
cb (undefined, cats);
});
};
So this example doesn't exactly show an advantage, but if you had an addCat route, then the route could use a "getCatById" function call, verify the cat doesn't exist, and add it. It also helps with some nesting. The routes could also be used for sanitizing the objects before sending them off, and might also send resources and information used in UI that isn't necessarily coupled with mongoose. It also allows interactions with the database to be reusable in multiple routes.