Mongodb with Node Js - 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" }])

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

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

Mongoose populate schema from different Database

For example i have SchemaA and SchemaB which both belong to different database. Inside SchemaA i have doc.b = {type: mongoose.Schema.Types.ObjectId, ref: 'SchemaB'}. When i am doing populate of this i got below error. MissingSchemaError: Schema hasn't been registered for model "SchemaB". Use mongoose.model(name, schema) From my research i have read that mongoose support population cross databases.
I am requiring mongoose multiple times for each schema, is that the problem?
Basically what i need is two different schema which is connecting to different databases to work together with populate. If i register schema on connection created by mongoose they will not be registered on the same list. If there a way to success that?
Basically what we need to do is pass schema to population, something like this:
User.findOne({
_id: req.user._id
}).populate({
path: 'roomsContainer',
model: RoomsContainer,
populate: [{
path: 'creator'
},{
path: 'users'
},{
path: 'rooms',
model: Room
}]
}).exec(function(err, user) {
// do some magic
});
Where User belong to database one and Room, RoomsContainer belong to database two.
const db1 = mongoose.createConnection('mongodb://localhost:27000/db1');
const db2 = mongoose.createConnection('mongodb://localhost:27001/db2');
const conversationSchema = new Schema({ numMessages: Number });
const Conversation = db2.model('Conversation', conversationSchema);
const eventSchema = new Schema({
name: String,
conversation: {
type: ObjectId,
ref: Conversation // `ref` is a **Model class**, not a string
}
});
const Event = db1.model('Event', eventSchema);
Refrence here

mongoose - storing an array of ids in mongoDB at storage time, but getting entire objects back at runtime?

I am trying to setup a mongoose model of what I want in my mongodb instance.
here is the code I have for a user type so far.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema(
{
username: String,
userType: int,
tagline: String,
friends: <Not sure what to do here>
}));
Essentially, I want to only store the ids of other users in here at insert time etc, but when I query to GET this user, I want to actually get the json that would have the various users I want to get back.
Mongoose provides a mechanism for referencing other collections and populating them. I'm making the assumption the _ids in friends are other Users so you can define your schema as
module.exports = mongoose.model('User', new Schema(
{
username: String,
userType: int,
tagline: String,
friends: [{type: ObjectId, ref: 'User'}]
}));
And then you can use the built in populate method in mongoose to retrieve the actual documents and not just the _ids
User
.findOne({ username: username })
.populate('friends')
.exec(function (err, user) {
if (err) return handleError(err);
console.log(user.friends);
});
I need to use Population. So you define your fields as ref:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
username: String,
userType: int,
tagline: String,
friends:[{type: Schema.ObjectId, ref: 'User'}]
}));
And could fetch your friends as array of objects via .populate method:
User.findById(id)
.populate('friends')
.exec(function (err, user) {
if (err) throw err;
// user.friends is array of users
console.log(user.friends)
})

Use populate() for two different schemas in MongoDB

I have two MongoDB collections - comments
var mongoose = require('mongoose');
var CommentSchema = new mongoose.Schema({
body: String,
author: String,
upvotes: {type: Number, default: 0},
post: { type: mongoose.Schema.Types.ObjectId, ref: 'Profile' }
});
mongoose.model('Comment', CommentSchema);
and users
var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
userName: String,
userJobRole: String,
userEmail: String,
userPhone: String,
userTimeZone: String,
post: { type: mongoose.Schema.Types.ObjectId, ref: 'Profile' }
});
mongoose.model('User', UserSchema);
I want to use populate for each of these schemas in my get request. One for users and one for comments from these models.
router.get('/profiles/:profile', function(req, res, next) {
req.post.populate('users', function(err, post) {
if(err) { return next(err) }
res.json(post);
});
});
I can only figure out how to call one.
Does Mongoose allow you to populate from two schemas?
In order to populate multiple paths, you can pass a space delimited string of path names to the populate method on any document as follows:
Story
.find(...)
.populate('fans _creator') // space delimited path names
.exec()
This is taken directly from the Mongoose docs http://mongoosejs.com/docs/populate.html

Resources