Not 100% certain if what I want to achieve is the correct way of doing it, so please correct me if I'm wrong.
I'm building a nodejs, express & passport website/app.
In my routes.js, I have the following section:
/* GET Home Page */
router.get('/dashboard', isAuthenticated, function(req, res){
res.render('dashboard', {
user: req.user,
sess: req.session
});
});
After the user is logged in, it displays the 'dashboard'. On that 'dashboard' I'd like to include 10 of their recent logbook entries. I have logbook.js model set up, I'm just unsure how to call it.
My function within models/logbook.js is:
function getLatestEntries(req, res, user){
Logbook.find({ 'uid' : user.uid }, {}, { limit: 10}, function(err, logbook){
return logbook;
});
}
Contents of logbook.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var logbookSchema = new Schema({
id: String,
uid: String,
lid: { type: String, unique: true},
callsign: String,
contact: String,
start: String,
end: String,
band: String,
mode: String,
RSTsent: String,
RSTrec: String,
notes: String
});
var Logbook = mongoose.model('Logbook', logbookSchema);
function getLatestEntries(req, next){
Logbook.find({ 'uid' : sess.uid }, {}, { limit: 10}, function(err, logbook){
if (err){
console.log("Error"+err)
return next(err, null);
}
return next(null, logbook);
});
}
module.exports.getLatestEntries = getLatestEntries;
// make this available to our users in our Node applications
module.exports = Logbook;
In your routes.js:
var Logbook = require('./models/logbook'); // change path if it's wrong
/* GET Home Page */
router.get('/dashboard', isAuthenticated, function(req, res, next) {
Logbook.find({ 'uid' : req.user.uid }, {}, { limit: 10}, function(err, logbook){
if (err) { console.log(err); return next(); }
res.render('dashboard', {
user: req.user,
logbook: logbook
});
});
});
In your models/logbook.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var logbookSchema = new Schema({
id: String,
uid: String,
lid: { type: String, unique: true},
callsign: String,
contact: String,
start: String,
end: String,
band: String,
mode: String,
RSTsent: String,
RSTrec: String,
notes: String
});
var Logbook = mongoose.model('Logbook', logbookSchema);
// make this available to our users in our Node applications
module.exports = Logbook;
Related
I am trying to read data from the mongo database , but I am getting error.
I will explain what I did.
create two schema
let CompanySchema = new Schema({
name: {type: String, required: true, max: 100},
contactPerson: {type: String},
});
// Export the model
module.exports = mongoose.model('Company', CompanySchema);
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'companyId' }
});
// Export the model
module.exports = mongoose.model('UserTest', UserSchema);
First, add one company like this.which is successfully added
app.get('/addCompany', async (req, res) => {
let company = new Company({
name: 'Test 1',
contactPerson: 'rajesh'
})
company.save(function (err) {
if (err) {
console.log(err);
res.status(500).send(err);
// return next(err);
}
res.send('company added successfully')
//res.render('index', { title: 'Express'})
});
})
Then I added a user like this .which is successfully added.
app.get('/addUser', async (req, res) => {
let user = new User({
name: 'Test 1',
companyId: '5d3d46b2825d7f0eaf9d9d27'
})
user.save(function (err) {
if (err) {
console.log(err);
res.status(500).send(err);
// return next(err);
}
res.send('user added successfully')
//res.render('index', { title: 'Express'})
});
})
Now I am trying to fetch all user with company detail and getting error
app.get('/getUser', async (req, res) => {
User
.find({})
.populate('companyId') // only works if we pushed refs to person.eventsAttended
.exec(function(err, data) {
if (err) {
console.log(err)
return;
}
res.send(data);
});
})
error
MissingSchemaError: Schema hasn't been registered for model "companyId".
Use mongoose.model(name, schema)
at new MissingSchemaError (/Users/b0207296/WebstormProjects/untitled2/node_modules/mongoose/lib/error/missingSchema.js:22:11)
at NativeConnection.Connection.mode
Can you try now after changing your second schema to this :
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'Company' }
});
module.exports = mongoose.model('UserTest', UserSchema);
Assuming companyId's has matching documents in _id's of Company. Similar kind of functionality can also be achieved thru $lookup of mongoDB.
in ref you should pass the Company instead of company id
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'Company' }
});
In my program I want to populate my index page with a model called a group. Previously I just showed all the groups that existed in the database, but now I want to only show the groups that the user who is logged in is associated with.
Here are the models:
Group Model
var mongoose = require("mongoose");
var groupSchema = new mongoose.Schema({
name: String,
thumbnail: String,
description: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
inviteCode: String,
images: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Image"
}
],
users: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
] });
module.exports = mongoose.model("Group", groupSchema);
User Model
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
groups:
[
{
type: mongoose.Schema.Types.ObjectId, //referencing model by id
ref: "Group" //name of the model
}
],
images:
[
{
type: mongoose.Schema.Types.ObjectId, //referencing model by id
ref: "Image" //name of the model
}
]
});
UserSchema.plugin(passportLocalMongoose); //add in local mongoose methods to user
module.exports = mongoose.model("User", UserSchema);
My Index Route:
//Index Route
router.get("/", middleware.isLoggedIn, function(req, res){
var user = req.user;
user.populate("groups").exec(function(err, allGroups){
if(err){
console.log(err);
} else {
res.render("groups/show", {groups: allGroups});
console.log(allGroups);
}
});
});
And this is the error I get:
TypeError: user.populate(...).exec is not a function
I am not sure why I cant use the populate method with my user model, can someone explain me an alternative to achieve the desired outcome. Thank you.
I think the problem is that req.user is not a schema, so .populate is not a method carried by that variable in its object prototype. Hence the terminal telling you it's not a function.
You have to require the User schema like this in your index route:
const User = require("./models/user");
Then find the user by its id then populate it:
//Index Route
router.get("/", middleware.isLoggedIn, function(req, res){
var user = req.user;
User.findById(req.user._id, function(err, foundUser) {
let user = foundUser;
user.populate("groups").exec(function(err, allGroups){
if(err){
console.log(err);
} else {
res.render("groups/show", {groups: allGroups});
console.log(allGroups);
}
});
});
});
Let me know if it works!
my objective is to push a message into the messages property (which is an array) of a user object using Mongoose. However, I get an error when I try to save the user (user.save()). I did these three console.logs on the code below to see what went wrong. Can someone fix this?
console.log(user.messages);
user.messages.push(result._id);
console.log(user.messages)
user.save(function (err, result) {
console.log(err)
});
So, one before I push the message into the array, one right after and one to check the error after I tried to save the user. This gave me the following logs:
first, an empty array
[]
second, an array containing the message ID
["5a5cdd894504771c80c8901a"]
Third, the error why it didn't save the user properly:
{ MongoError: Unknown modifier: $pushAll
at Function.MongoError.create (C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb-core\lib\error.js:31:11)
at toError (C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb\lib\utils.js:139:22)
at C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb\lib\collection.js:1059:67
at C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb-core\lib\connection\pool.js:469:18
at process._tickCallback (internal/process/next_tick.js:150:11)
name: 'MongoError',
message: 'Unknown modifier: $pushAll',
driver: true,
index: 0,
code: 9,
errmsg: 'Unknown modifier: $pushAll' }
This is the code on the server side (node.js)
router.post('/', function (req,res,next){
// We stored the user in the token so we can retrieve it from this token.
// fetch the user (in the token) who reached this route
// we use the jwt package to decode the token ( we wont be able to grab the user if we skip this step)
// the decode method does not check if the token is valid, this happens
// higher up in this file. we only decode it to grab the user. If we hadn't
// protected our route we wouldve had to use a different strategy (.verify method)
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function(err, user){
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
var message = new Message({
content: req.body.content,
user: user._id
});
message.save(function(err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
console.log(user.messages);
user.messages.push(result._id);
console.log(user.messages)
user.save(function (err, result) {
console.log(err)
});
res.status(201).json({
message: 'Saved message',
// this object is what we'll receive in the front-end
// and what we'll convert using the response.json() method
obj: result
});
});
});
});
This is the user Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
according to this issue, $pushAll has beed deprecated, you can get around this by setting { usePushEach: true } in you schema options
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
}, { usePushEach: true });
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
I'm new to MongoDB/Mongoose and trying to figure out how to map relationships between Schema. I don't think issue is with .populate(). At creation of new user and clients, I do not see the relationship reflected in collection
User (login via local/social) has many Clients.
A set of Clients belong to 1 User
Is this the correct way to declare foreign key? {type: Schema.Types.ObjectId, ref: 'Client'}
Should both Schema have the each other's foreign key to relate to one another?
Is there any additional code required when creating User/Client in order for the data from foreign key to show up? I read something about populate()
User
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
local: {
id: String,
email: String,
password: String,
name: String,
mobile: String,
clients: {type: Schema.Types.ObjectId, ref: 'Client'}
},
google: {
id: String,
token: String,
email: String,
name: String,
clients: {type: Schema.Types.ObjectId, ref: 'Client'}
}
});
module.exports = mongoose.model('User', userSchema);
Client
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var clientSchema = new Schema({
id: String,
firstname: String,
lastname: String,
mobile: String,
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
module.exports = mongoose.model('Client', clientSchema);
Create User
app.post("/api/user", function (req, res) {
const user = req.body;
console.log(user);
User.findOne({ 'local.email': user.email },
function (err, result) {
if (err) {
console.log(err);
handleError(err, res);
return;
}
if (result) {
res.status(500).send("Email already exists in database");
} else {
var newUser = new User();
newUser.local.password = generateHash(user.password);
newUser.local.email = user.email;
newUser.local.name = user.name;
newUser.local.mobile = user.mobile;
newUser.save(function (err, result) {
res.status(201).send("User added to database");
});
}
});
});
Create Client
app.post("/api/client", function (req, res) {
const client = req.body;
console.log(client);
Client.findOne({
$and: [
{ firstname: client.firstname },
{ lastname: client.lastname }
]
},
function (err, result) {
if (err) {
console.log(err);
handleError(err, res);
return;
}
if (result) {
res.status(500).send({msg:"Client already exists in database"});
} else {
var newClient = new Client();
newClient.firstname = client.firstname;
newClient.lastname = client.lastname;
newClient.mobile = client.mobile;
newClient.save(function (err, result) {
res.status(201).send("Client added to database");
});
}
});
});
I am getting the correct data for friendRequests which is getting a user ID and throwing it in the friendRequest field of my mongoose file. When I add $push to add the data into the friendRequest array in the route file, it actually does not insert it and gives me back the err function I created.
Here is my route file:
exports.addContactPost = function(req, res, err) {
User.findByIdAndUpdate(req.signedCookies.userid, {
$push: {friendRequest: req.body.friendRequest}
}, function(err) {
if(err) {
console.log("post2");
return console.log('error');
}
else {
console.log('postsuccess');
res.json({response: true});
}
});
};
Here is the mongoose file:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt-nodejs'),
SALT_WORK_FACTOR = 10;
var UserSchema = new Schema({
email: { type: String, required: true, lowercase:true, index: { unique: true } },
password: { type: String, required: true },
firstName: {type: String, required: true},
lastName: {type: String, required: true},
phone: {type: Number, required: true},
birthday: {type: Date, required: true},
friendRequest: {type: Array},
friend: {type: Array}
});
UserSchema.pre('save', function(next) {
var user = this;
console.log("email exists");
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password along with our new salt
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
module.exports = mongoose.model('User', UserSchema);
So the document that mongo finds matching the provided userId does not have an array as its friendRequest property. Look at that specific document by ID in mongo shell and fix it so that friendRequest is an array.