I am trying to use MongoDB collections and relate one collection to another. I have one collection named "player" and one named "calendar", and I am trying to add player info to calendar events so only the player logged into the system can see their specific events.
I can see all the info of the event when I console log req.body:
{ start_date: '2019-02-09 00:00',
end_date: '2019-02-09 00:05',
text: 'New event',
id: '5c5a6bc5ea427e54cd4714d6',
'!nativeeditor_status': 'updated' }
The id you are seeing is the EVENT id. I want to add a field userID using passport (req.user.id) that way I can then search the collection and populate events of the logged in player.
My question is how to add fields to the req.body element? My calendar and player schemas are as follows:
player.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
calendar: {
type: Schema.Types.ObjectId, ref: 'calendar'
}
});
const User = mongoose.model('player', UserSchema);
module.exports = User;
calendar.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const schema = new Schema({
text: {type: String, required: true},
start_date: {type: Date, required: true},
end_date: {type: Date, required: true},
user: {type: Schema.Types.ObjectId, ref: 'player', required: true}
});
const calendar = mongoose.model('calendar', schema);
module.exports = calendar;
Here is how I'm implementing the calendar in my route index.js:
//schedule
router.get('/calendar', ensureAuthenticated, function(req, res){
req.body.user = req.user.id;
var db = require('mongoskin').db("mongodb://tdipietro87:tdipietro87#tmcluster-shard-00-00-pbtwu.mongodb.net:27017,tmcluster-shard-00-01-pbtwu.mongodb.net:27017,tmcluster-shard-00-02-pbtwu.mongodb.net:27017/test?ssl=true&replicaSet=TMCluster-shard-0&authSource=admin&retryWrites=true", { w: 0});
db.bind('calendar');
var Calendar = require('../models/calendar');
Calendar.find({user: req.user.id}) // query by specific user
.then(function (data) {
// ...
router.use(express.static(path.join(__dirname, 'public')));
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
router.get('/init', function(req, res){
db.calendar.insert({
text:"My test event A",
start_date: new Date(2018,8,1),
end_date: new Date(2018,8,5)
});
db.calendar.insert({
text:"My test event B",
start_date: new Date(2018,8,19),
end_date: new Date(2018,8,24)
});
db.calendar.insert({
text:"Morning event",
start_date: new Date(2018,8,4,4,0),
end_date: new Date(2018,8,4,14,0)
});
db.calendar.insert({
text:"One more test event",
start_date: new Date(2018,8,3),
end_date: new Date(2018,8,8),
color: "#DD8616"
});
res.send("Test events were added to the database")
});
router.get('/data', function(req, res){
db.calendar.find().toArray(function(err, data){
//set id property for all records
console.log(err);
for (var i = 0; i < data.length; i++)
data[i].id = data[i]._id;
//output response
res.send(data);
});
});
router.post('/data', function(req, res){
console.log(req.body);
console.log(req.user.id);
var data = req.body;
var mode = data["!nativeeditor_status"];
var sid = data.id;
var tid = sid;
delete data.id;
delete data.gr_id;
delete data["!nativeeditor_status"];
function update_response(err, result){
if (err)
mode = "error";
else if (mode == "inserted")
tid = data._id;
res.setHeader("Content-Type","application/json");
res.send({action: mode, sid: sid, tid: tid});
}
if (mode == "updated")
db.calendar.updateById( sid, data, update_response);
else if (mode == "inserted")
db.calendar.insert(data, update_response);
else if (mode == "deleted")
db.calendar.removeById( sid, update_response);
else
res.send("Not supported operation");
});
res.render('calendar', {
name: req.user.name
})
});
});
This is very complicated to answer, but i want to give some clue
const newEvent = new Calendar({ //Calendar is your models name
....fill with another required field in models
text : req.body.text,
user : req.user.id //look again, how you decode incoming token request and declare them
});
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!
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 new to express/mongoose and trying to implement User-Post relationship.Aka 1:Many.
I have two models,
// *models/user.js
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
email: {type: 'string'},
password: {type: 'string'},
posts: [{type: mongoose.Schema.Types.ObjectId, ref: 'Post'}]
});
module.exports = mongoose.model('User', userSchema);
// *models/post.js
var mongoose = require('mongoose');
var postSchema = mongoose.Schema({
user : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
body: String,
title: String
});
module.exports = mongoose.model('Post', postSchema);
server.js,
Post = require('./models/post');
User = require('./models/user');
app.post('/api/posts',(req,res)=>{
User.findOne({email: "valid_email"},(err, user)=>{
var post = {
title: "Post 1 Title",
body: "Post 1 body",
user: user._id
}
Post.create(post, (err, post)=>{
res.send(post);
});
});
});
Now, this approach is working for saving the Post which belongs to user with email "valid_email".I can reach out it's user by populating.
app.get('/post', (req,res)=>{
Post.findOne(title: "Post 1 title")
.populate('user')
.exec(function (err, user) {
if (err) throw err;
console.log(user._id, user.email);
res.end();
});
});
I thought generating a Post in the callback of finding a User would automatically push it to User's posts.Not only it is not how it works, i can't push manually to "user.posts".
It says can't "push" to undefined.When i console.log(user.posts) i get undefined.
How is it that i can generate a Post belongsTo a User, then i can populate the user just by it's id, but can't push a Post to User? It gives undefined "user.posts" ?
!!! I got it working.
app.post('/api/posts', (req,res)=>{
User.findOne({id: _some_user_id}, (err,user)=>{
var poster = user;
var post = {title: req.body.title, body: req.body.body, category: req.body.category, user: poster}
Post.create(post, (err,post)=>{
res.send(post);
poster.posts.push(post);
poster.save();
});
});
});
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;