I have a Users model structure somewhat like this:
const userSchema = new mongoose.Schema({
email: { type: String, unique: true },
password: String,
todosDo: [models.Do.schema],
}
And the child "Do" schema somewhat like this (in a different file):
const doSchema = new mongoose.Schema({
name: {type: String, default : ''},
user: {type: mongoose.Schema.ObjectId, ref: 'User'},
createdAt: {type : Date, default : Date.now}
});
And I'm trying to figure out how to retrieve the todosDo array for the signed in user. This is what I've got so far:
// Get all "Do" todos from DB
// Experimenting to find todos from certain user
User.findById(req.user.id, function(err, user){
if(err){
console.log(err);
} else {
doTodos = user.todosDo, // this obviously doesn't work, just an idea of what I was going for
console.log(doTodos);
finished();
}
});
Am I referencing the child/parent wrong or am I just not retrieving the array right? Any help is greatly appreciated!
As far I guess you may want to edit as raw js objects so you need to use lean() function. without using lean() function user is mongoose object so you can't modify it.
can try this one:
User.findById(req.user.id)
.lean()
.exec(function (err, user) {
if(err){
console.log(err);
return res.status(400).send({msg:'Error occurred'});
}
if(!user) {
return res.status(400).send({msg:'User Not found'});
}
doTodos = user.todosDo;
console.log(user.todosDo); // check original todos
console.log(doTodos);
return res.status(200).send({doTodos : doTodos }); // return doTodos
});
and to refer child schema in parent schema from different model you can access a Model's schema via its schema property.
say in doSchema.js file
const doSchema = new mongoose.Schema({
name: {type: String, default : ''},
user: {type: mongoose.Schema.ObjectId, ref: 'User'},
createdAt: {type : Date, default : Date.now}
});
module.exports = mongoose.model( 'DoSchema', doSchema );
in user.js file
var DoModel = require('./doSchema');// exact path
const userSchema = new mongoose.Schema({
email: { type: String, unique: true },
password: String,
todosDo: [DoModel.schema],
}
Thanks for your help everybody! My problem was that I needed to push all the newly created todos in the post route to todosDo, so then I could retrieve them at the get route. Everything's working now!
Related
I trying to edit and update a form using mongoose. The code seems fine to me, but it doesn't work. I have tried so many ways but the updated version is still the same, I uses a put route to send the form, when I output req.body.studentInfo to the console, it is correct, but the update remains the same. Please help
This is my schema
var mongoose = require("mongoose");
var uniqueValidator = require('mongoose-unique-validator');
var passportLocalMongoose = require("passport-local-mongoose");
var mongoose = require("mongoose");
var UserSchema = new mongoose.Schema({
studentInfo: {
first_name: String,
middle_name: String,
last_name: String,
street: String,
town: String,
city: String,
region: String,
country: String,
studentId: String,
day: Number,
month: String,
year: Number,
},
username: {type: String, required:true, unique:true},
passport: String
});
UserSchema.plugin(uniqueValidator);
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("StudentInfo", UserSchema);
This is my App.js
app.put('/:id', function(req,res){
StudentInfo.findByIdAndUpdate(req.params.id, {$set: req.body.studentInfo}, function(err, updated){
console.log(req.params.id);
console.log(req.body.studentInfo);
if(err) {
console.log(err);
}
else {
res.redirect('/' + req.params.id);
}
});
});
The studentInfo is an object that contains the names of each variables in my form which I name was studentInfo[name of variable]. Please help
It should be specified that mongoose should return the updated document - by default it returns the original (this is also the behavior of mongodb). I think that if the code gets changed to this:
StudentInfo.findByIdAndUpdate(req.params.id, {$set: req.body.studentInfo}, { new: true }, function(err, updated){
...
});
you will receive the updated document in the callback.
As #Denny mentioned in his answer, mongoose will not return the updated document in the callback until you pass {new : true } option.
For Details and available options check findByIdAndUpdate Docs
Question, I got a schema using mongoose which created an Object. I don't know how to query the author id which will return the list of the object under the author Id
var mongoose = require("mongoose");
var bookedSchema = new mongoose.Schema({
origin: String,
destination: String,
author: { id: { type: mongoose.Schema.Types.ObjectId, ref: "User"}, username: String},
Date: {type: Date, default: Date.now}
});
module.exports = mongoose.model("Booked", bookedSchema);
On my route I have query find({}) i want to query the author id instead of {} and it will return the list of object under the author ID. i tried the findById(author:{id:req.user._id}) but it returned null answer. any ideas how to do that. Thank You!
router.get('/myAccount', function(req, res){
Booked.find({}).exec(function(err, booked){
if(err){
console.log(err);
// res.redirect('back');
}else{
console.log(booked)
res.render('accounts/myAccount', {booking:booked});
}
});
});
you should use .populate() for refered documents to populate them.
change this:
Booked.find({}).exec(function(err, booked)
to:
Booked.find({}).populate('author').exec(function(err, booked)
or if you need to find a document by the refered author id you can use this:
Booked.find({}).populate({
path: 'author',
match: { id: { $eq: req.user._id }}
}).exec(function(err, booked)
I've got two models in mongoose:
const user = mongoose.Schema({
name: String,
...
});
and
const moderator = mongoose.Schema({
name: String,
...
});
When I access these collections with:
user.find()
I get in response list of users and moderators separetly.
What I want to achive is to join these two list together to get a list based on this model:
const myDataSchema = mongoose.Schema({
user: {type: Schema.Types.ObjectId, ref: 'user'},
moderator: {type: Schema.Types.ObjectId, ref: 'moderator'}
});
Where one of attributes (either user or moderator) will be set.
I solved my problem. Instead of using the mongoose schema I created my "own object". My code:
let list= [];
users.forEach( function (user)
{
list.push({user: user});
});
moderators.forEach( function (moderator)
{
list.push({moderator: moderator});
});
It's probaly not the most efficient way but it works.
I am trying to build a forum in order to learn the MEAN stack. I ran into an issue while using mongoose...
I have this...
var UserSchema = new Schema({
id: ObjectId,
firstName: String,
lastName: String,
role: String,
email: {
type: String,
unique: true
},
password: String,
workers: [WorkerSchema]
});
var TopicSchema = new Schema({
id: ObjectId,
title: String,
moderator: UserSchema,
posts: [PostSchema]
});
var Topic = mongoose.model('Topic', TopicSchema);
app.post('/topics', requireLogin, function(req, res) {
User.findOne({"email": req.session.user.email}, function(err, user) {
if (user.role == "moderator" || user.role == "admin") {
var topic = new Topic({
title: req.body.title,
moderator: req.session.user,
posts: []
});
topic.save(function(err) {
if (err) console.log(err);
res.status(204).end();
});
}
});
});
My issue is this... When I POST a topic to /topics, it works the first time, populating the topics collection with one item. But then, when I POST to /topics again, from the same user, I get an E11000 MongoError that looks like this:
message: 'E11000 duplicate key error index: MY_MONGO_DB.topics.$moderator.email_1 dup key: { : "myuser#example.com" }'
I know that removing the 'unique: true' property from the email field of UserSchema would fix this issue, but I don't want to remove that uniqueness property since I use it elsewhere in my code to ensure that users are unique by email.
Is there any way around this? In other words, is there any way to keep the 'unique: true' property and also retain the ability of users to be able to post multiple topics without triggering the E11000 error?
What you did was to embed the user. In your database, the resulting document would look something like
{
...
moderator: {..., email: "john#example.com"}
}
Which, of course, would violate the unique constraint if you have the same person as a moderator twice.
What you should do instead is to reference the user in your schema:
var user = mongoose.model('User', UserSchema);
var TopicSchema = new Schema({
id: ObjectId,
title: String,
moderator: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
posts: [PostSchema]
});
I've got the following schemas:
var userSchema = new Schema({
firstName: String,
lastName: String,
emailAddress: {type: String, set: toLower, index: {unique: true}},
});
var eventMemberSchema = new Schema ({
user: { type : Schema.ObjectId, ref : 'User' },
created: { type: Date, default: Date.now }
});
var eventSchema = new Schema({
id : String,
name : String,
startDate : Date,
endDate : Date,
venue : { type : Schema.ObjectId, ref : 'Venue' },
invitees : [eventMemberSchema],
});
What I'm trying to do, is query the events, with an invitation._id, and ultimately get back the user...
invitees->eventMember->user
So far i've got:
Event
.find({ "invitees._id": req.query.invitation_id })
.populate('user')
.run(function (err, myEvent) {
console.log('error: ' + err);
console.log('event: '+ myEvent);
})
This works, and console shows the output of myEvent...
(I realise I don't need the populate part of my mongoose query above for this... i'm just testing)
I'm struggling on how to get, what I'd basically describe as: myEvent.invitees.user
EDIT
As an update...
This works - however, it kind of sucks, as now i'll need to do another db operation to get the user (i realise ref in mongoose does this under the hood)
Event
.findOne({ "invitees._id": "4f8eea01e2030fd11700006b"}, ['invitees.user'], function(err, evnt){
console.log('err: '+ err);
console.log('user id: '+ evnt.invitees[0].user); //this shows the correct user id
});
Try
Event
.find({ "invitees._id": req.query.invitation_id })
.populate('invitees.user')
Update:
Here is a working gist.