How do I make sure that this variable gets defined? - javascript

I have this variable Blog which is a mongoose model. It gets defined here:
db.once("open", function(){
var userSchema = new mongoose.Schema({
username: String,
password: String
});
var blogSchema = new mongoose.Schema({
title: String,
content: String,
userId: String
});
User = mongoose.model("User", userSchema);
Blog = mongoose.model("Blog", blogSchema);
});
I want to use app.get to generate a url that looks like /post/blogpost_id/edit so I tried to do this:
Blog.find(function (err, posts){
app.get("/post/" + posts._id + "/edit/", checkAuth, function(req, res){
res.render("edit.html", {
pageTitle: "Edit",
pages: {
"Log Out": "/logout"
},
posts: posts
});
});
});
As you can imagine, that doesn't work. How can I fix this?

The reason is that Blog gets defined in an asynchronous callback, so your code gets further executed while node is waiting for the database to be opened and therefore will not be defined yet.
Also the defining of your route is extremely inefficient. You should define a route with a parameter: /post/:postID/edit and inside the callback check whether the post with the given ID exists. It will look like this afterwards (note that I don't know mongoose and wrote this after a quick check of the manual):
app.get("/post/:postID/edit/", checkAuth, function (req, res) {
Blog.find({ _id: req.params.postID }, function (err, posts) {
if (posts.length == 0) res.send(404, 'Not found');
else // yadayada
});
});

Related

schema error mean app

I have a schema problem. I dont get the right schema in my api. here is my api :
var Meetup = require('./models/meetup');
module.exports.create = function (req, res) {
var meetup = new Meetup(req.body);
meetup.save(function (err, result) {
console.log(result);
res.json(result);
});
}
module.exports.list = function (req, res) {
Meetup.find({}, function (err, results) {
res.json(results);
});
}
The console.log displays { __v: 0, _id: 58343483ff23ad0c40895a00 } while it should display { __v: 0, name: 'Text input', _id: 58343076b80874142848f26e }
here is my model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Meetup = new Schema({
name: String,
});
module.exports = mongoose.model('Meetup', Meetup);
If req.body is undefined (as you wrote in the comments) then obviously new Meetup(req.body); cannot populate the new objects with any data (like {name: 'Text input'} or anything else) since it is called with undefined as an argument.
Make sure you use the body-parser and that you pass the correct data in your request.
Also, check for errors. Every callback that takes the err argument should be in the form of:
module.exports.list = function (req, res) {
Meetup.find({}, function (err, results) {
if (err) {
// handle error
} else {
// handle success
}
});
}
How to track the problem:
make sure you use the body-parser on the backend
make sure you pass the correct data on the frontend
make sure that the data passed by your frontend is in the correct place (body)
make sure that the data is in the correct format (JSON? URL-encoded?)
add console.log(req.body) after new Meetup(req.body); to know what you save
open the Network tab in the developer console of your browser and see what is transferred

How do I use Angular Controller to get data from Mongo database

I am trying to use controllers to modify a page according to the user.
I am using this:
$http.get('/someUrl').then(function(response){
$scope.firstname = response.data;
});
What I am trying to do is, get each of the fields from my database and use them accordingly.
If this is my schema and I already have a person stored in the database:
var personSchema = new mongoose.Schema({
firstname: {type: String, required: true, },
lastname: {type: String, required: true}
});
var person = mongoose.model('People', personSchema);
module.exports = person;
What URL will I use in '/someUrl' to get the firstname of the person that is currently signed in?
Also, am I missing any functionality that I need to execute this?
EDIT:
My route
router.post("/update-profile", function(req, res) {
if (!req.session.user) {
return res.status(401).send();
}
var firstname = req.body.firstname;
var lastname = req.body.lastname;
var newProfile = new UserProfile();
newProfile.firstname = firstname;
newProfile.lastname = lastname;
console.log(newProfile);
newProfile.save(function(err, savedProfile) {
if (err) {
console.log(err);
return res.status(500).send();
} else {
res.render("profile");
return res.status(200).send();
}
});
});
Get a person object from the url.
$http.get('/user?id=5').then(function(response){
$scope.user = response.data;
});
Where the id is the user id.
Then in your html you can use {{user.firstName}}.
You could also pass in req.user to the page when it loads, so you wouldn't need to do another get.
res.render('page',{user:req.user});
Then (in ejs)
$scope.user = <%=user%>;
What I feel is, you should have an end-point /api/users/:id that should expect an _id as request parameter.
So your get request would be like :
$http.get('/someUrl/' + current_logged_in_user_id).then(function(response){
$scope.firstname = response.data;
});
And your backend code would be something like:
app.get('/someUrl/:id', function(req, res){
User.findById(req.params.id, function (err, user) {
if(user) res.json(user.firstName);
});
});
Now from the information that you provided, that's the best I can tell you. You can use DaftMonk's Angular Fullstack Generator. It creates the whole Authentication Boilerplate for you. It automatically get user details based on session_id and adds the user to req.user. So in the request handler, you can simply get the requesting user's details by using req.user

Saving objects in two ways, what is the difference?

I'm learning Angular by following this tutorial. No what I don't get is why is there two ways of saving/editing an object? They don't really explain it.
first way (in the index.js router):
router.post('/posts', function(req, res, next) {
var post = new Post(req.body);
post.save(function(err, post) {
if (err) { return next(err); }
res.json(post);
});
});
second way (in the mongoose model):
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
mongoose.model('Post', PostSchema);
The two ways are actually the same.
In the first example a new instance of Post is created. The save is called on this instance because it exists on PostSchema (inherited from Mongoose Schema).
In the second example we define a new method on PostSchema so when invoked, this refers to the instance of the Post.
The cb parameter is a callback which is normally a function.
Look at this example.
router.post('/posts', function(req, res, next) {
var post = new Post(req.body);
post.save(function(err, post) {
if (err) { return next(err); }
var callback = function(err, post) {
console.log("Upvoted");
res.json(post);
}
post.upvote(callback);
});
});
Here a new post is created with one upvote by default.
A new instance of Post is created and saved in the db. After save, upvote method is called. After the upvote was saved in the db, the new post is returned in the response.
Hope this helps.
The first part is a normal Mongoose save in which you create a new object from the schema. The second is having a method defined in the schema to handle the save.
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
For example, assuming I already have a saved post and I want to upvote it. I can have a route like this:
router.put('/post/:id/upvote', function(req, res, next) {
Post.findOne({_id: req.params.id}, function (error, post) {
post.upvote(function(error, post) {
res.json(post);
});
});
});
In simple terms, the code above makes use of the inbuilt "upvote" method that is already defined in the Schema, so all objects created from the Schema will have an "upvote" method that will increase the number of upvotes. It is the same thing as doing this:
router.put('/post/:id/upvote', function(req, res, next) {
Post.findOne({_id: req.params.id}, function (error, post) {
post.upvotes += 1;
post.save(function(error, post) {
res.json(post);
});
});
});
Just that it is cleaner and saves you a few keystrokes.

Unable to update an object inside MongoDB collection using HTTP Put?

I am new to AngularJS and I was trying to update my MongoDB Database. I am having an issue when I am trying to update an object inside my collection. The following is my attempt at trying to do so:
//listviewFactory is already injected and returns an event object
//I call $scope.put when clicking (ng-click) on a button
$scope.event = listviewFactory.getEvent();
$scope.put = function(event){
var currentUser = {};
if($cookieStore.get('token')) {
currentUser = User.get();
}
event.attendees.push(currentUser);
$http.post('/api/events/' + event._id, event).success(function(data){
for(var i = 0; i < event.attendees.length; i++){
console.log("Attendees: ", event.attendees[i]);
}
$location.path('/');
});
};
I'm just unsure of why my code isn't working. When I do the $http put request, my function is successful and proceeds to perform the console.log. When I print out the attendees array, I saw that the currentUser object is indeed appended to my event.attendees array. However, when I check my database using the Mongo shell, My attendees array is not updated and remains blank. Any ideas on why or where I may be wrong at? Below is also my server side code in how I am routing my application and specifying how to store the information in MongoDB.
module.exports = function(app) {
app.use('/api/events', require('./api/event'));
...
}
module.exports = mongoose.model('Event', EventSchema);
var express = require('express');
var controller = require('./event.controller');
var router = express.Router();
router.get('/', controller.index);
router.put('/:id', controller.update);
// Updates an existing event in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Event.findById(req.params.id, function (err, event) {
if (err) { return handleError(err); }
if(!event) { return res.send(404); }
var updated = _.merge(event, req.body);
updated.save(function (err) {
if (err) { return handleError(err); }
return res.json(200, event);
});
});
};
EDIT: When I console.log currentUser:
Current User:
Resource {$promise: Object, $resolved: false, $get: function, $save: function, $query: function…}
$promise: Object
$resolved: true
__v: 0
_id: "53dd72fb5a24aa781a3cbde8"
email: "test#test.com"
name: "Test User"
provider: "local"
role: "user"
EDIT: Mongoose schema:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var EventSchema = new Schema({
startDate: Date,
endDate: Date,
eventLocation: String,
eventName: String,
attendees: Array
});
I assume you are using mongoose. Try
updated.markModified('attendees');
before
updated.save call.
Regarding pushing the currentUser, do something equivalent to
event.attendees.push({__v: 0
_id: "53dd72fb5a24aa781a3cbde8"
email: "test#test.com"
name: "Test User"
provider: "local"
role: "user"})
i.e just push the relevant fields.

How to inserting a document with field referencing document in another collection

I am currently attempting to create a .post function for a schema with document reference. However, I am not sure how I can retrieve the ObjectID of the document reference from another collection.
Board.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BoardSchema = new Schema({
boardname: String,
userid: {type: Schema.ObjectId, ref: 'UserSchema'}
});
module.exports = mongoose.model('Board', BoardSchema);
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String
});
module.exports = mongoose.model('User', UserSchema);
routes.js
router.route('/boards')
.get(function(req, res) {
Board.find(function(err, boards) {
if(err)
res.send(err);
res.json(boards);
});
})
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
res.send(err);
board.userid = user._id;
});
board.save(function(err) {
if(err)
res.send(err);
res.json({message: 'New Board created'});
});
});
To create the board, I include a boardname and a username in my request. Using the username, I do a User.find to find the specific user and assign it to board.userid. However, this does not seem to be working as board.userid does not appear.
Any help would be greatly appreciated!
Thank you!
EDIT
A better explanation of what is required is that I have an existing User collection. When I want to add a new document to Board, I would provide a username, from which I would search the User collection, obtain the ObjectId of the specific user and add it as userid to the Board document.
I believe you are looking for population
There are no joins in MongoDB but sometimes we still want references
to documents in other collections. This is where population comes in.
Try something like this:
//small change to Board Schema
var BoardSchema = new Schema({
boardname: String,
user: {type: Schema.ObjectId, ref: 'User'}
});
//using populate
Board.findOne({ boardName: "someBoardName" })
.populate('user') // <--
.exec(function (err, board) {
if (err) ..
console.log('The user is %s', board.user._id);
// prints "The user id is <some id>"
})
Sorry, I solved a different problem previously. You'll probably want to use the prevoius solution I provided at some point, so I'm leaving it.
Callbacks
The reason the userid is not on the board document is because User.find is asynchronous and is not assigned at the moment board.save(...) is called.
This should do the trick:
(Also, I added a couple of returns to prevent execution after res.send(...))
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
return res.send(err); //<-- note the return here!
board.userid = user._id;
board.save(function(err) {
if(err)
return res.send(err); //<-- note the return here!
res.json({message: 'New Board created'});
});
});
});

Categories

Resources