I am trying to access the data in my User-Model (using Express, Pug and Mongoose).
This is my schema:
var userSchema = mongoose.Schema({
userData: {
name: { type: String, required: true, unique: true },
password: String
},
notes: [ String ],
contacts: [{
name: String,
notes: [ String ]
}],
locations: [ String ]
});
This is my pug-template file:
each user in allUsers
p #{user.userData.name}
My Route looks like this:
app.get('/', function(req, res) {
if (app.locals.userData.name) {
res.render('app', {
currentUser: app.locals.userData,
allUsers: User.find({})
});
} else {
res.redirect('signup');
}
});
Where could be my mistake?
The Browser shows a Cannot read property 'name' of undefined error.
I had to use the callback function!!!
app.get('/', function(req, res) {
User.find({}, function(err, users) {
if (app.locals.userData.name) {
res.render('app', {
currentUser: app.locals.userData,
allUsers: users
});
} else {
res.redirect('signup');
}
});
});
Related
I'm trying to create a route where it takes in a parameter for a username and then displays that users information. Only thing is, the username is in the user schema from when the user signs up. The profile schema references the user schema. How do I use the username parameter in the findOne call to display the users profile data?
User schema:
const UserSchema = new Schema({
username: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("users", UserSchema);
Profile schema:
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users"
},
name: {
type: String
},
image: {
type: String
},
bio: {
type: String
},
location: {
type: String
},
website: {
type: String
},
social: {
youtube: {
type: String
},
facebook: {
type: String
},
instagram: {
type: String
},
twitter: {
type: String
}
}
});
module.exports = User = mongoose.model("profile", ProfileSchema);
Route:
router.get("/user/:username", (req, res) => {
const errors = {};
Profile.findOne({ user: req.params.user.username })
.populate("user", "username")
.then(profile => {
if (!profile) {
errors.noprofile = "There is no profile for this user";
return res.status(404).json(errors);
}
res.json(profile);
})
.catch(err => res.status(404).json(err));
});
Please try this :
router.get("/user/:username", async (req, res) => {
const errors = {};
try {
const profile = await User.aggregate([
{ $match: { username: req.params.username } },
{ $lookup: { from: "profile", localField: "_id", foreignField: "user", as: "userProfile" } },
{ $project: { userProfile: { $arrayElemAt: ["$userProfile", 0] }, username: 1, _id:0 } }
]).exec();
if (!profile.length) {
errors.noprofile = "There is no profile for this user";
return res.status(404).json(errors);
}
res.json(profile[0]);
} catch (error) {
console.log('Error in retrieving user from DB ::', error);
return res.status(404);
}
})
Try using aggregate, firstly you check-in user table for getting details of a specific username then fetch the profile details as below using lookup, if no profile found after unwind the document will not be fetched and you can check on aggregate result's length as aggregate always return an array in result :
User.aggregate([
{$match:{ username: req.params.user.username }},
{$lookup:{from:"profile",localField:"_id",foreignField:"userId",as:"profileData"}},
{$unwind:"$profileData"},
{$project:{profileData:1,username:1}}
{$limit:1}
])
.then(profile => {
if (!profile.length) {
errors.noprofile = "There is no profile for this user";
return res.status(404).json(errors);
}
res.json(profile[0]);
})
You can do it in 2 steps.
Look for users containing username in userSchema, get it's id.
Then in promise, use that id to, look for profileSchema contains.
router.get("/user/:username", (req, res) => {
users.findOne({ username: req.params.username }).then(_user=>{
profile.findOne({ user: _user._id }).populate('user').then(_profile => {
res.json(_profile);
})
})
});
This code will look for username in userSchema and look for userSchema's id in profileSchema then returns profileSchema populated with user.
I am developing an application in which I need to send an array with the time and amount of food. When I print the console log on the front (vuejs and axios), I can see the array with the correct information, but when I send that array to the back (express and mongoose) it arrives as Undefined. I am providing below the front my functions and the code of my back.
I`m using MongoDB as database.
Could you please help me?
FRONTEND: (vuejs)
addMealList() {
if (this.editedIndex > -1) {
Object.assign(this.mealList[this.editedIndex], this.mealInformations);
console.log(this.mealList);
} else {
this.mealList.push(this.mealInformations);
console.log(this.mealList);
}
this.close()
},
addToAPI() {
// console.log(this.mealList);
axios.post(`${this.serverUrl}devices/register`, this.mealList)
.then((res) => {
console.log(this.mealList);
console.log(res.data);
})
.catch((error) => {
console.log(error);
});
},
```
BACKEND: (mongoose and express)
Schema File:
```
const mongoose = require('mongoose');
const mealSchema = new mongoose.Schema({
time: {
type: String,
required: true
},
quantity: {
type: String,
required: true
}
});
const deviceSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
mealList: [mealSchema],
creation_information: {
date: {
type: Date,
default: Date.now
},
by: {
type: String,
required: true
}
}
}, { collection : 'device' });
module.exports = mongoose.model('device', deviceSchema);
Express code:
router.post('/register', (req, res) => {
console.log(req.body.mealList);
console.log(req.user);
const device = new Device({
_id: new mongoose.Types.ObjectId(),
mealList: [ req.body.mealList ],
creation_information: {by: req.user._id}
});
console.log(device);
if (device.mealList && device.mealList.length) {
device.save().then(result =>{
console.log(result);
res.status(201).json({
message: "Hadling POST requests to device",
createdDevice: result
});
})
.catch(err =>{
console.log(err);
res.status(500).json({
error: err
})
});
}else {
console.log('array is empty');
}
});
I expected to see my Meals array with time and quantity, but I`m getting this on my terminal
undefined
{ _id: 5cfbde0d5bd9cd0e168f14cf,
mealList: [ undefined ],
creation_information: { by: 'Lorena Meyas', date: 2019-06-08T16:10:53.756Z } }
{ _id: 5cfbde0d5bd9cd0e168f14cf,
mealList: [ undefined ],
creation_information: { by: 'Lorena Meyas', date: 2019-06-08T16:10:53.756Z },
__v: 0 }
I created login & registration page and users data is being stored in user collection. Also did functionality for adding & viewing new post created by loggedin user. So whenever a user is creating the post, I need to refer the user data (username) in post collection. I have checked some forums, but not able to understand populate method. I need to know about referencing data in schema and how to fetch the data from user collection and use it in post collection.
Here is the User Model
var UserSchema = new mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
profileimage: {
type: String
},
uposts: [{ type: Schema.Types.ObjectId, ref: 'Post'}]
});
var User = module.exports = mongoose.model('User', UserSchema);
Here is the Post Model
var PostSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
postimage: {
type: String
},
author: {
type: Schema.Types.ObjectId,
ref: "User"
// username: String
},
});
var Post = module.exports = mongoose.model('Post', PostSchema);
Route for adding new post
router.post('/add', upload.single('postimage'), (req, res, next) => {
if(req.file) {
console.log('Uploading File..');
var postimage = req.file.filename;
} else {
console.log('No File Uploaded');
var postimage = 'noimage.jpg';
}
var newPost = new Post({
postimage: postimage
});
Post.createPost(newPost, (err, post) => {
if(err) throw err;
console.log(post);
});
req.flash('success', 'Successfully Created Posts');
res.location('/');
res.redirect('/');
});
Router for displaying Posts
router.get('/view', ensureAuthenticated, (req, res, next) => {
// res.render('viewpost', { user: req.user });
Post.find({_id: {$ne: req.user._id}}, (err, posts) => {
if(err) {
console.log(err);
} else {
res.render('viewpost', {currentUser: req.user, posts: posts});
}
});
});
Also I need to display the post details of other users except the loggedin user.
It would be really helpful, if you could provide a suitable method for the same.
Before Apply please check mongoDB version,
router.get('/view', ensureAuthenticated, async(req, res, next) => {
try {
const posts = await Post.aggregate([
{
$match: { userId: { $ne: req.user._id }}
},
{
$lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user"
}
},{
$project: {
postimage: "$postimage",
user: { $arrayElemAt: ["$user", 0] }
}
}
])
res.render('viewpost', {currentUser: req.user, posts: posts, error: ''});
} catch(error) {
res.render('viewpost', { currentUser: req.user, posts: [], error: error});
}
})
If no result found please make req.user._id as ObjectId using mongoose.Types.ObjectId(req.user._id)
I'm trying to create a "wishlist" feature for users on my node / mongo application. I've assumed the best way to model the scheme would be to reference the items they like. So far my reading has brought me to this point (I'm not very familiar with the Types.ObjectID):
Schema Model
var UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
required: true
},
wishlist: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Wishlist",
required: true
}]
});
I've managed to write some code which pushes the relevant _id into the "Likes" array:
Product.findById(productID).exec(function (err, user) {
User.updateOne({ _id: req.session.userId }, { "$push": { "wishlist": productID } }, function (err, user) {
if (err) {
console.log("Failed to add")
} else {
console.log(productID + " has been added")
}
});
});
This outputs in the database like so:
{
"_id" : ObjectId("5c3f7e1f1268203b1f31cb17"),
"email" : "email",
"password" : "password",
"__v" : 0,
"wishlist" : [
ObjectId("5c41f4b42f82b14798d5c7fc"),
ObjectId("5c41f4b42f82b14798d5c7ff")
]
}
I'm stuck on how I'd output these wishlist items in my template. My assumption was to get the data like this:
router.get('/wishlist', middleware.requiresLogin, function(req, res, next) {
User.findOne({ _id: req.session.userId }, function(err, user) {
res.render('wishlist', {
title: 'Wishlist',
template: 'wishlist',
saved: user.wishlist,
header: true,
footer: true
});
});
});
And the loop through the items like this:
{{#each saved }} Code goes here {{/each }}
Am I approaching this correctly?
you'll need to populate the wishlist field, try this,
User.findOne({ _id: req.session.userId }).
populate('wishlist').
exec(function (err, user) {
res.render('wishlist', {
title: 'Wishlist',
template: 'wishlist',
saved: user.wishlist,
header: true,
footer: true
});
});
You can refer to the Populate (mongoose documentation).
//User_controller.js
exports.getUser = (req, res) => {
User.findOne({ _id: req.session.userId })
.populate('wishlist')
.then((user) => { res.json(user) })
.catch((error) => { res.status(500).json({ error })
});
};
// UserRoute.js
const express = require("express");
const router = express.Router();
const userCtrl = require('./user_controller');
router.get('/:id', userCtrl.getUser);
module.exports = router;
//server.js
//...
const userRoute = require("./UserRoute");
app.use("/user", userRoute);
//...
I am using Mongoose with Express.
I want to check if a username is already taken.
var isNew = function(req, res, next) {
if (User.find({ 'userData.name': { $exists: false } })) {
next();
} else {
res.redirect('/');
}
}
my Schema:
var userSchema = mongoose.Schema({
userData: {
name: { type: String, required: true, unique: true },
password: String
},
imagePath: { type: String, required: true },
notes: [ String ],
contacts: [{
name: String,
notes: [ String ]
}],
locations: [ String ]
});
The below code will work assuming you are passing in json with a name attribute in the request body.
var isNew = function(req, res, next) {
User.count({ 'userData.name': req.body.name.toLowerCase() },
function (err, count) {
if (err) {
return next(err);
} else if (count) {
return next();
} else {
res.redirect('/');
}
});
}