Mongoose Foregin Key mapping - javascript

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");
});
}
});
});

Related

How to use populate method of mongoose for mongodb in node js?

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' }
});

Mongoose findOne.populate scope issue

There is a array of user IDs in currentUser.follow. Each user has posts with referenceId of PostSchema . Now I want to populate each user's post and store it in an array[userArray]. But due to scope issue the array remains empty. Please show me how I can get all the users with their post in the Array[userArray]
app.js
app.get("/", isLoggedIn, function(req, res){
var currentUser =req.user;
var userArray=[];
for(let fol of currentUser.follow){
User.findById(fol).populate("posts").exec(function(err, user){
if(err){
console.log(err);
}else{
console.log(user); // a user with populated posts
userArray.push(user);
console.log(userArray); //stores user but posts is not populated
}
});
}
console.log(userArray); // empty array
});
User Schema
var mongoose =require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
name: String,
email: String,
username: String,
password: String,
posts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Post"
}
],
follow: [String]
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
Post Schema
var mongoose =require("mongoose");
var PostSchema = new mongoose.Schema({
text: String,
image: String,
author:{
id:{
type: mongoose.Schema.Types.ObjectId,
ref : "User"
},
username: String
},
createdAt: {type:Date, default:Date.now}
});
module.exports= mongoose.model("Post", PostSchema);
Because User.findById is asynchronous so the second console.log(userArray); will excute before the result pushed to userArray.
There is a better way to do this with $in operator and async/await:
app.get("/", isLoggedIn, async function(req, res){
try {
var currentUser = req.user;
var userArray = await User.find({_id: {$in: currentUser.follow}}).populate("posts");
console.log(userArray);
} catch(err) {
console.log(err);
}
});

Mongoose connect existing DB

I'm trying to understand how MongoDB works.
I created a local MongoDB with the following collection:
db.user.find().pretty()
{
"_id" : ObjectId("5a05844833a9b3552ce5cfec"),
"firstname" : "Emanuel",
"lastname" : "Mars",
"username" : "mae",
"email" : "myEmail#email.ch",
"passwort" : "mae",
"role" : 1
}
Now, I want to connect to the DB with Express.
The connection works, but I don't get any data.
This is the model I created:
var userSchema = new mongoose.Schema({
firstname: { type: String },
lastname: { type: String },
username: { type: String },
email: { type: String },
passwort: { type: String },
role: { type: Number }
}, { collection : 'user' });
module.exports = mongoose.model('user', userSchema);
And this is how I want to get all Users in the collection user:
var User = require('../../models/user');
User.find({}, function (err, user) {
console.log('yes', user);
});
Upon success, it should handle a login process with users from the MongoDB.
Solved:
I forgot to add the DB name at the end of the connect URL.
//server.js
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
const db = mongoose.connection;
db.on('error', () => {
console.log('DB connection Error');
});
db.once('open', () => {
console.log('DB is connected');
});
require('./config/passport')(passport);
//user.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
var userSchema = new mongoose.Schema({
firstname: { type: String },
lastname: { type: String },
username: { type: String },
email: { type: String },
passwort: { type: String },
role: { type: Number }
}, { collection : 'user' });
userSchema.methods.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};
userSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.local.password);
};
module.exports = mongoose.model('user', userSchema);

Creating dynamic Mongoose models with prefix

I would like to create mongoose model dynamically with a prefix variable.
I have a First UserSchema
var UserSchema = new Schema({
username: String,
blogs : [{type: mongoose.Schema.Types.ObjectId, ref: 'Blog' }],
)};
module.exports = mongoose.model('User', UserSchema);
And a BlogShema
var BlogSchema = new Schema({
blogName: String,
posts : [{type: mongoose.Schema.Types.ObjectId, ref: prefix + 'Post' }]
)};
module.exports = mongoose.model('Blog', BlogSchema);
Then a PostSchema
var PostSchema = new Schema({
blog: { type: String, ref: 'Blog' },
title: String,
content: String
)};
module.exports = mongoose.model(prefix + 'Post', PostSchema);
Each Schema is on separate js files:
posts.server.model.js
blogs.server.model.js
users.server.model.js
I would like the prefix variable in mongoose.model(prefix + 'Post', PostSchema); to get the value of username String from UserSchema which passed form a signup form through
require('../../models/users.server.model.js');
require('../../models/blogs.server.model.js');
require('../../models/posts.server.model.js');
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
mongoose = require('mongoose'),
User = require('mongoose').model('User'),
Blog = require('mongoose').model('Blog'),
Post = require('mongoose').model(prefix + 'Post');
passport.use('local-signup', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done) {
process.nextTick(function() {
User.findOne({ username : username }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'Username is already taken.'));
} else {
var newUser = new User();
newUser.username = username;
newUser.password = password;
newUser.email = req.body.email;
newUser.save(function(err) {
if (err)
throw err;
var site = new Site({user : newUser.username, siteTitle: newUser.username});
site.save(function(err) { // create website
if (err) {
return next(err);
} else {
newUser.sites.push(site); // push site'id in sites field in user
newUser.save(); // save user after site'id has been push
for (var i=0; i<basePages.length; i++) { // create pages from base.json file
var page = new Page(basePages[i]);
page.save(function(err, page) { // create page
if (err) {
return next(err);
} else {
site.pages.push(page); // push page'id in pages field in site
site.save(); // save site after pages'id has been push
};
});
};
return done(null, newUser);
};
});
});
};
});
});
}));
For resume, If signup username is john during signup I would like to create a johnpost collection john posts.

How to push returned value into an array mongodb?

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.

Categories

Resources