Mongoose populate not working. How to resolve? - node.js

I want to do mongoose populate but it not working below is given my schema. How can I solve this issue? Why is it not working I working many solution on stackoverflow but all are not working even I read out doc that also not worked for me. Now someone can please help me How can I sort it?
Auth
const authSchema = mongoose.Schema({
first_name: {
type: String
},
last_name: {
type: String
},
});
const auth = mongoose.model('auth', authSchema);
Project
const teamSchema = mongoose.Schema({
auth_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'auth'
}
});
const projectSchema = mongoose.Schema({
team: {
type: [ teamSchema ]
}
});
const project = mongoose.model('project', projectSchema);
Query:
project.find({}).populate(team.$.auth_id).exec((err, result) => {
if(err) rej(err);
res(result);
});

Based on the documentation you should do something like:
project.find({}).populate('team').exec..... or project.find({}).populate('auth_id').exec.....
If you want to filter an specific auth_id the criteria should be in the find not in the populate, populate apparently receives key name to be populated
https://mongoosejs.com/docs/populate.html
Hope this help

For me, the verison of mongoose 6.* don't work populate.
I stay hour to descover.
try downgrade your mongoose to versions 5.*
commands:
yarn remove mongoose
yarn add mongoose#5.13.14

I think you need to create a virtual.
something like:
userSchema.virtual('car', {
ref: 'Car',
localField: '_id',
foreignField: 'owner',
});

Related

MissingSchemaError: Schema hasn't been registered for model "Review". Use mongoose.model(name, schema) [duplicate]

I'm using the MEAN stack and when I try to start the server using npm start, I get an exception saying that:
schema hasn't been registered for model 'Post'. Use mongoose.model(name, schema)
Here is my code inside /models/Posts.js:
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
as I can see the schema should be registered for the model 'Post', but what is causing the exception to be thrown?
Edit: Here's the exception error:
/home/me/Documents/projects/personal/flapper-news/node_modules/mongoose/lib/index.js:323
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "Post".
Use mongoose.model(name, schema)
and here's the app.js code with the mongoose initialization:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
before the line:
app.use('/', routes);
It's not an issue with model export. I had the same issue.
The real issue is that require statements for the models
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
were below the routes dependencies. Simply move the mongoDB dependencies above the routes dependencies. This is what it should look like:
// MongoDB
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
If someone coudn't fix it with the approach of the correct answer (like me), try to look at the creation of the schema. I wrote the 'ref' as 'User', but the correct was 'user'.
Wrong:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User'
}
Correct:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user'
}
IF YOU USE MULTIPLE mongoDB CONNECTIONS :
beware that when using .populate() you MUST provide the model, as mongoose will only "find" models on the same connection.
ie where:
var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
"name": String,
"email": String
});
var customerSchema = mongoose.Schema({
"name" : { type: String },
"email" : [ String ],
"created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});
// model creation - notice the registered model name as first parameter
var User = db1.model('_users_', userSchema);
var Customer = db2.model('_customers_', customerSchema);
Correct approach:
// you can pass a model instance
Customer.findOne({}).populate('created_by', 'name email', User)
Customer.findOne({}).populate({ path: 'created_by', select: 'name email', model: User })
// you can pass the model NAME as string (even from variable)
Customer.findOne({}).populate('created_by', 'name email', '_users_')
Customer.findOne({}).populate({ path: 'created_by', model: '_users_' })
var otherSchemaName = '_'+'users'+'_'
Customer.findOne({}).populate({ path: 'created_by', model: otherSchemaName})
Incorrect (produces "schema hasn't been registered for model" error):
Customer.findOne({}).populate('created_by');
It seems Mongoose have now included this case in their docs based on this answer ;)
see: https://mongoosejs.com/docs/populate.html#cross-db-populate
I used the following approach to solve the issue
const mongoose = require('mongoose');
const Comment = require('./comment');
const PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: Comment }]
});
mongoose.model('Post', PostSchema);
Please look, here ref don't have string type value, now it's referring to Comment schema.
Here's https://mongoosejs.com/docs/populate.html#cross-db-populate
It says we have to pass the model as a third argument.
For e.g.
//Require User Model
const UserModel = require('./../models/User');
//Require Post Model
const PostModel = require('./../models/Post');
const posts = await PostModel.find({})
.select('-__v')
.populate({
path: 'user',
select: 'name -_id',
model: UserModel
});
//or
const posts = await PostModel.find({})
.select('-__v')
.populate('user','name', UserModel);
this problem happens when you use a model that depends on another model, but that other model didn't get registered yet.
a simple fix would be
adding model to popualte instead of depending on ref in the schema
=>> example
const jobs = await Job.find({}).populate({
path: "jobDescriptions",
model: JobDesc,
select: "list",
populate: {
path: "list",
select:"name list",
model: Skill,
},
});
The issue is with the refs, always make sure to refer the refs to whatever name your are exporting from the models.
// Model
const Task = mongoose.model('**Tasks**', taskSchema);
//Refs
userSchema.virtual('tasks', {
ref: '**Tasks**',
localField: '_id', // field in current model
foreignField: 'owner' // corresponding field in other model
});
This error also pops up when we create wrong references (ref) between mongoose models.
In my case I was referring to the file name instead of model name.
eg:
const userModel = mongoose.model("user", userSchema);
We should refer to 'user' (model name) instead of 'User' (file name);
.\nodeapp\node_modules\mongoose\lib\index.js:452
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "users".
Use mongoose.model(name, schema)
at new MissingSchemaError
I got this error resolved when use setTimeout on server.js
mongoose.connect(env.get('mongodb.uri'), { useNewUrlParser: true })
.then(() => logger.info("MongoDB successfully connected"))
.catch(err => logger.error(err));
app.use(passport.initialize());
setTimeout(function() {
require("./src/utils/passport")(passport);
}, 3000);
import User from '..'
Customer.findOne({}).populate({ path: 'created_by', model: User })
This answer works for me.
However You're going to have to import the model instead of setting it into cote
I was also facing the same problem.
The solution to my problem was looking at the ref parameter which had a different name compared to the model I was actually exporting and hence no such model was found.
userSchema.virtual('tasks', {
ref: 'Task',
localField: '_id',
foreignField: 'owner'
})
Whereas what I had actually exported was :-
const Tasks = mongoose.model('Tasks', taskSchema)
module.exports = Tasks
After rectifying the Task as Tasks my problem was solved
Elaborating on Rafael Grilli's answer above,
Correct:
var HouseSchema = new mongoose.Schema({
date: {type: Date, default:Date.now},
floorplan: String,
name:String,
house_id:String,
addressLine1:String,
addressLine2:String,
city:String,
postCode:String,
_locks:[{type: Schema.Types.ObjectId, ref: 'xxx'}] //ref here refers to the first parameter passed into mongoose.model()
});
var House = mongoose.model('xxx', HouseSchema, 'houseschemas');
You should also check that you don't have dirty data in your database. I ended up with a document containing the lowercased version of the referenced model (user instead of User). This causes the error and is incredibly hard to track down.
Easy to fix with a quick mongo query:
db.model.updateMany({ approvedByKind: 'user' }, { $set: { approvedByKind: 'User' } })
In my case, this issue because I haven't included the model or ref model into the application.
So you should required Post model and Comment model in your node application.
Refer the same name that you refer in model name while creating new model.
For example: if I have mongoose model like:
var Post = mongoose.model("post",postSchema);
Then I have to refer to posts collection via writing ref:"post".
My problem was sort out using the below
adminModel.findById(req.params.id).populate({
path: "users",
model: userModel //User collection name
})
Just wanted to add that for me I was using destructuring when importing the Schema which was causing it to fail.
Correct
var intakeSchema = require('../config/models/intake')
Incorrect
var { intakeSchema } = require('../config/models/intake')
You're not giving the model any value
In my case, I was using a model for which I didn't updated when making the MongoDB connection.
So, I had something like
const Device = require('../../models/device')
// make use of Device
with this connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User])
Fix
You have to add the model to the conn when initiating the connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User, Device])
Note that I added Device to the connection.
I just face the same problem.
I created reviews for products. then I deleted them. whenever mongoose tried to populate the data of deleted items Mongoose Schema hasn't been registered for model error was showing.
After dropping the review collection the error was gone.
I also facing same issue but i resolved by removing module.exports
module.exports = mongoose.model('user', userSchema); // remove module.exports
and use like:: mongoose.model('user', userSchema);
const mongoose = require('mongoose');
const ObjectId = require('mongoose').ObjectId;
var userSchema = new mongoose.Schema({
Password: { type: String },
Email: { type: String, required: 'This field is required.', unique:true },
songs: [{ type: ObjectId, ref: 'Songs'}]
});
// Custom validation for email
userSchema.path('Email').validate((val) => {
emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
// module.exports = mongoose.model('user', userSchema); // remove 'module.exports ='
mongoose.model('user', userSchema); // resolved issue

Mongodb with Node Js

How can i execute this mongodb query through node js (mongoose).
i have two tables with the follwoing schemas,
i want to fetch username and password from users table and fetch full name from the info table.
var infoSchema = mongoose.Schema({
khatam_id: String,
user_id: String,
fullname: String,
});
var usersSchema = mongoose.Schema({
user_id: String,
username: String,
password: String,
});
i don't know if you're a hot shot but if you are you can use this.
userSchema.virtual('infos',
{
ref: 'Info',
localField: 'user_id',
foreignField: 'user_id',
})
Assuming u name you're infoSchema as Info model ,mongodb converts it to infos in case you didn't know thats why the virtual field will be called as infos ref obviously a reference to Info model
localField is the field referring the userSchema unique id and foreignField is the field u are referring in the infoSchema which matches the unique value that localfield u mentioned .
Finally, along with all the fields in your userSchema add this
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
so when u query for user
Give it a shot it really comes in handy.
Note: it doesn't actually create a field in the database (virtual duh.) it just populates your response object for front end rendering which is actually better.
Connect to MongoDB: Make sure MongoDB service is running before the program execution.
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/your-database");
mongoose.Promise = global.Promise;
var connection = mongoose.connection;
connection.once('open', function() {
console.log('connected to database);
});
connection.on('error', function() {
console.error('Mongoose connection error");
});
process.on('SIGINT', function() {
mongoose.connection.close(function() {
console.log('Mongoose connection disconnected due to app SIGINT.');
});
});
create user schema :
const Schema = mongoose.Schema;
const usersSchema = new Schema({
user_id: String,
username: String,
fullname: String
});
const Users = mongoose.model('Users', usersSchema );
Run Query like this:
Users.findOne({query})
.then(function(user){
// do something
})
.catch(function(err){
// handle error
})
Assuming you know how to set setup mongoose and connect your database and only need the correct query let me share something i noticed with the models you provided. I don't think there is a need for 2 collections as you can store the same thing under one collection because it saves the time for lookup for the user data from info schema. So user schema can be
var usersSchema = mongoose.Schema({
user_id: String,
username: String,
password: String,
khatam_id: String,
fullname: String
});
And using the following query you can get the user details
Users.findOne({})
.then(function(user){
// do something
})
.catch(function(err){
// handle error
})
This is much more efficient and faster compared to using aggregate queries or mongoose populate functions.
If the above method is not suitable for you you can try the mongoose populate function.
UserSchema = new mongoose.Schema({
user_id: String,
password: String,
},
// schema options: Don't forget this option
// if you declare foreign keys for this schema afterwards.
{
toObject: {virtuals:true},
// use if your results might be retrieved as JSON
// see http://stackoverflow.com/q/13133911/488666
//toJSON: {virtuals:true}
});
UserInfoSchema = new mongoose.Schema({
user_id: String,
khatam_id: String,
username: String,
fullname: String,
});
// Foreign keys definitions
UserSchema.virtual('userDetails', {
ref: 'UserInfoSchema',
localField: 'user_id',
foreignField: 'user_id',
justOne: true // for many-to-1 relationships
});
// Models creation
var UserSchema = mongoose.model('UserSchema', UserSchema);
var UserInfoSchema = mongoose.model('UserInfoSchema', UserInfoSchema);
// Querying
UserSchema.find({...})
// if you use select() be sure to include the foreign key field !
.select({.... user_id ....})
// use the 'virtual population' name
.populate('userDetails')
.exec(function(err, books) {...})
install mongoose in your machine
npm install mongoose
import mongoose lib
const mongoose = require('mongoose');
const Schema = mongoose.Schema, ObjectId = Schema.ObjectId;
connect to mongodb and create schema for your table
mongoose.connect('mongodb://localhost/myappdatabase');
const usersSchema = new Schema({
_id: ObjectId,
user_id: String,
username: String,
fullname: String
});
const Users = mongoose.model('Users', usersSchema );
Find user from "Users" table using mongo query
Users.find({<here you can write your mongo query>}, function (err, docs) {
// docs.forEach
});
you have to use aggregate
db.users.aggregate([
{
$lookup:
{
from: "info",
localField: "user_id",
foreignField: "_id",
as: "userInfo"
}
},
{ "$unwind": "$userInfo" },
])
You can use this query to get those types of records what you want:
db.users.aggregate([
{ $lookup: {
from: "info",
localField: "user_id",
foreignField: "user_id",
as: "userInfo"}},
{ "$unwind": "$userInfo" }])

MissingSchemaError: Schema hasn't been registered for model "User". when trying to execute the code at CLI [duplicate]

I'm using the MEAN stack and when I try to start the server using npm start, I get an exception saying that:
schema hasn't been registered for model 'Post'. Use mongoose.model(name, schema)
Here is my code inside /models/Posts.js:
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
as I can see the schema should be registered for the model 'Post', but what is causing the exception to be thrown?
Edit: Here's the exception error:
/home/me/Documents/projects/personal/flapper-news/node_modules/mongoose/lib/index.js:323
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "Post".
Use mongoose.model(name, schema)
and here's the app.js code with the mongoose initialization:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
before the line:
app.use('/', routes);
It's not an issue with model export. I had the same issue.
The real issue is that require statements for the models
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
were below the routes dependencies. Simply move the mongoDB dependencies above the routes dependencies. This is what it should look like:
// MongoDB
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
If someone coudn't fix it with the approach of the correct answer (like me), try to look at the creation of the schema. I wrote the 'ref' as 'User', but the correct was 'user'.
Wrong:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User'
}
Correct:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user'
}
IF YOU USE MULTIPLE mongoDB CONNECTIONS :
beware that when using .populate() you MUST provide the model, as mongoose will only "find" models on the same connection.
ie where:
var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
"name": String,
"email": String
});
var customerSchema = mongoose.Schema({
"name" : { type: String },
"email" : [ String ],
"created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});
// model creation - notice the registered model name as first parameter
var User = db1.model('_users_', userSchema);
var Customer = db2.model('_customers_', customerSchema);
Correct approach:
// you can pass a model instance
Customer.findOne({}).populate('created_by', 'name email', User)
Customer.findOne({}).populate({ path: 'created_by', select: 'name email', model: User })
// you can pass the model NAME as string (even from variable)
Customer.findOne({}).populate('created_by', 'name email', '_users_')
Customer.findOne({}).populate({ path: 'created_by', model: '_users_' })
var otherSchemaName = '_'+'users'+'_'
Customer.findOne({}).populate({ path: 'created_by', model: otherSchemaName})
Incorrect (produces "schema hasn't been registered for model" error):
Customer.findOne({}).populate('created_by');
It seems Mongoose have now included this case in their docs based on this answer ;)
see: https://mongoosejs.com/docs/populate.html#cross-db-populate
I used the following approach to solve the issue
const mongoose = require('mongoose');
const Comment = require('./comment');
const PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: Comment }]
});
mongoose.model('Post', PostSchema);
Please look, here ref don't have string type value, now it's referring to Comment schema.
Here's https://mongoosejs.com/docs/populate.html#cross-db-populate
It says we have to pass the model as a third argument.
For e.g.
//Require User Model
const UserModel = require('./../models/User');
//Require Post Model
const PostModel = require('./../models/Post');
const posts = await PostModel.find({})
.select('-__v')
.populate({
path: 'user',
select: 'name -_id',
model: UserModel
});
//or
const posts = await PostModel.find({})
.select('-__v')
.populate('user','name', UserModel);
this problem happens when you use a model that depends on another model, but that other model didn't get registered yet.
a simple fix would be
adding model to popualte instead of depending on ref in the schema
=>> example
const jobs = await Job.find({}).populate({
path: "jobDescriptions",
model: JobDesc,
select: "list",
populate: {
path: "list",
select:"name list",
model: Skill,
},
});
The issue is with the refs, always make sure to refer the refs to whatever name your are exporting from the models.
// Model
const Task = mongoose.model('**Tasks**', taskSchema);
//Refs
userSchema.virtual('tasks', {
ref: '**Tasks**',
localField: '_id', // field in current model
foreignField: 'owner' // corresponding field in other model
});
This error also pops up when we create wrong references (ref) between mongoose models.
In my case I was referring to the file name instead of model name.
eg:
const userModel = mongoose.model("user", userSchema);
We should refer to 'user' (model name) instead of 'User' (file name);
.\nodeapp\node_modules\mongoose\lib\index.js:452
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "users".
Use mongoose.model(name, schema)
at new MissingSchemaError
I got this error resolved when use setTimeout on server.js
mongoose.connect(env.get('mongodb.uri'), { useNewUrlParser: true })
.then(() => logger.info("MongoDB successfully connected"))
.catch(err => logger.error(err));
app.use(passport.initialize());
setTimeout(function() {
require("./src/utils/passport")(passport);
}, 3000);
import User from '..'
Customer.findOne({}).populate({ path: 'created_by', model: User })
This answer works for me.
However You're going to have to import the model instead of setting it into cote
I was also facing the same problem.
The solution to my problem was looking at the ref parameter which had a different name compared to the model I was actually exporting and hence no such model was found.
userSchema.virtual('tasks', {
ref: 'Task',
localField: '_id',
foreignField: 'owner'
})
Whereas what I had actually exported was :-
const Tasks = mongoose.model('Tasks', taskSchema)
module.exports = Tasks
After rectifying the Task as Tasks my problem was solved
Elaborating on Rafael Grilli's answer above,
Correct:
var HouseSchema = new mongoose.Schema({
date: {type: Date, default:Date.now},
floorplan: String,
name:String,
house_id:String,
addressLine1:String,
addressLine2:String,
city:String,
postCode:String,
_locks:[{type: Schema.Types.ObjectId, ref: 'xxx'}] //ref here refers to the first parameter passed into mongoose.model()
});
var House = mongoose.model('xxx', HouseSchema, 'houseschemas');
You should also check that you don't have dirty data in your database. I ended up with a document containing the lowercased version of the referenced model (user instead of User). This causes the error and is incredibly hard to track down.
Easy to fix with a quick mongo query:
db.model.updateMany({ approvedByKind: 'user' }, { $set: { approvedByKind: 'User' } })
In my case, this issue because I haven't included the model or ref model into the application.
So you should required Post model and Comment model in your node application.
Refer the same name that you refer in model name while creating new model.
For example: if I have mongoose model like:
var Post = mongoose.model("post",postSchema);
Then I have to refer to posts collection via writing ref:"post".
My problem was sort out using the below
adminModel.findById(req.params.id).populate({
path: "users",
model: userModel //User collection name
})
Just wanted to add that for me I was using destructuring when importing the Schema which was causing it to fail.
Correct
var intakeSchema = require('../config/models/intake')
Incorrect
var { intakeSchema } = require('../config/models/intake')
You're not giving the model any value
In my case, I was using a model for which I didn't updated when making the MongoDB connection.
So, I had something like
const Device = require('../../models/device')
// make use of Device
with this connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User])
Fix
You have to add the model to the conn when initiating the connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User, Device])
Note that I added Device to the connection.
I just face the same problem.
I created reviews for products. then I deleted them. whenever mongoose tried to populate the data of deleted items Mongoose Schema hasn't been registered for model error was showing.
After dropping the review collection the error was gone.
I also facing same issue but i resolved by removing module.exports
module.exports = mongoose.model('user', userSchema); // remove module.exports
and use like:: mongoose.model('user', userSchema);
const mongoose = require('mongoose');
const ObjectId = require('mongoose').ObjectId;
var userSchema = new mongoose.Schema({
Password: { type: String },
Email: { type: String, required: 'This field is required.', unique:true },
songs: [{ type: ObjectId, ref: 'Songs'}]
});
// Custom validation for email
userSchema.path('Email').validate((val) => {
emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
// module.exports = mongoose.model('user', userSchema); // remove 'module.exports ='
mongoose.model('user', userSchema); // resolved issue

Schema referencing stores the whole value instead of ObjectId alone

Lately, I've been going through a course named The Web Developer Course.
In which the final project is based on Camps.
In the project, the comment database and the campground database are referenced, that is, the ObjectIds of the comments which are posted in a campground is stored in an array. This is what to be happened actually.
But in my case, the exact scenario's changed..When I try to Add a new comment what actually happens is that the total object gets stored in the comments array instead of the ObjectId of the comment.
I've almost gone through Stackoverflow seeking solution for my problem but failed.
I just wanted the ObjectId to be stored in the comments array instead it stores the whole Object which brings me problem in updating and deleting a comment. When I delete or update a comment the operation does happen in the Comments database but doesn't reflect in the Campgrounds database. Please help me with this issue. If anyone's taking the same course, Please give me solutions if you've experienced something like this already. The Schema are as given below
Campground Schema:
var mongoose = require("mongoose");
var campgroundSchema = mongoose.Schema({
campGroundName: String,
campGroundImage: String,
description: String,
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
],
addedBy: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
module.exports = mongoose.model("Campground", campgroundSchema);
Comment Schema:
var mongoose = require("mongoose");
var commentSchema = mongoose.Schema({
text: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
module.exports = mongoose.model("Comment", commentSchema);
Post request for creating a comment:
router.post("/", middleware.isLoggedIn, function(req, res) {
Comment.create(req.body.comment, function(err, createdComment) {
if(err) {
console.log(err);
} else {
createdComment.author.id = req.user._id;
createdComment.author.username = req.user.username;
createdComment.save(); Campground.findById(req.params.id).populate("comments").exec(function(err, foundCampground){
foundCampground.comments.push(createdComment);
foundCampground.save();
req.flash("success" , "Comment created successfully");
res.redirect("/index/" + req.params.id);
});
}
});
});
The whole source code is below,
https://1drv.ms/u/s!AmISAco3PGaPhQl_Riu8nroCom5h
Please help me fix this issue!
you have this line:
foundCampground.comments.push(createdComment)
which is telling mongodb to store the whole comment in the array.
it should be this instead:
foundCampground.comments.push(createdComment._id)
which will only push the id property of the comment into the array.
The version seemed to have a bug in it.
The problem was fixed when I updated it. Fixed version is 5.0.3

nodejs mongoose many-to-many relation on MongoDB

I'm trying to make a many-to-many relation between two documents in mongoose. Just can't make it work.
I've been trying to utilize the mongoose populate method, but with no success. Does anyone know any good tutorials or example on how to take on the matter?
Update:
Got schemas
var EventSchema = new Schema({
users: [{
type: Schema.Types.ObjectId,
ref: 'User'
}]
});
and
var UserSchema = new Schema({
events: [{
type: Schema.Types.ObjectId,
ref: 'Event'
}]
});
In my tests I pused to event model user like so
event.users.push(user);
event.save(function(err, doc) {
user.events[0].should.equal(event._id);
done();
});
firstly I need to push somehow saved event to added user to event. Then by using populate I should can 'dress up' every object in events array and users array. Preferably in post save callback, if I understood populate correctly.
This test pases
it('creates', function(done) {
event.users.append(user);
event.save(function(err, ev) {
user.save(function(err, doc) {
doc.events[0].should.equal(ev._id);
doc.populate('events', function(err, d) {
console.log(d);
done();
});
});
});
});
So I know the ids are stored correctly, but when I run doc.populate() the returned document has events array empty. Just don't get it.
Made it work... used mongo-relation package to add the needed ids for me, but docs for this plugin made me change the schema form
var UserSchema = new Schema({
events: [{
type: Schema.ObjectId,
ref: 'Event'
}]
});
to
var UserSchema = new Schema({
events: [Schema.ObjectId]
});
once corrected, it worked.

Resources