Mongoose population ref - node.js

Hye!
This is an example of http://mongoosejs.com/docs
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
Story
.findOne({ title: 'Once upon a timex.' })
.populate('_creator')
.exec(function (err, story) {
if (err) return handleError(err);
console.log('The creator is %s', story._creator.name);
// prints "The creator is Aaron"
})
And that is my codeMy '_creator' is not an array but an array of objects :
var storySchema = Schema({
_creator : [{
_id : { type: Number, ref: 'Person' },
quantity : Number
}],
...
});
And my request is :
Story
.findOne({ title: 'Once upon a timex.' })
.populate('_creator._id')
.exec(function (err, story) {
if (err) return handleError(err);
console.log('The creator is %s', story._creator.name);
// prints "The creator is Aaron"
})
But this solution 'populate('_creator._id')' doesn't work.
Have you got an idea?
Thank you!

Related

Mongoose Refs to children

I am struggling to find examples or documentation on mongoose children population.
http://mongoosejs.com/docs/populate.html
On the documentation they have:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
It makes sense, a Person can have many stories thus the 'parent' field 'stories' which has a list of all the stories in.
What I am struggling to understand is how do you push the the story into the person schema.
For example, i have an assignment schema:
var mongoose = require ( 'mongoose' ),
Schema = mongoose.Schema;
var assignmentSchema = new Schema (
{
_id: String,
assignName: String,
modInsID: [{ type: Schema.Types.Number, ref: 'ModuleInst' }],
studentAssigns: [{type: Schema.Types.ObjectId, ref: 'StudentAssign' }]
}
);
module.exports = mongoose.model ( 'Assignment', assignmentSchema );
The studentAssigns stores all the id's of the studentAssigns which then can be used with the .pre middleware for cascade deleting.
So now my StudentAssign schema:
var mongoose = require ( 'mongoose' ),
autoIncrement = require ( 'mongoose-auto-increment' ),
Schema = mongoose.Schema;
var connection = mongoose.createConnection("************");
autoIncrement.initialize(connection);
var studentAssignSchema = new Schema (
{
assID: [{ type: Schema.Types.String, ref: 'Assignment' }],
studentID: [{ type: Schema.Types.Number, ref: 'Student' }]
}
);
var StudentAssign = connection.model('StudentAssign', studentAssignSchema);
module.exports = mongoose.model ('StudentAssign', studentAssignSchema );
As you can see it already is referencing 'Assignment'
Here is my api code:
studentAssign POST:
router.route('/student-assignment').post( function(req, res) {
var studentAssign = new StudentAssign();
studentAssign.assID = req.body.assID;
studentAssign.studentID = req.body.studentID;
studentAssign.save(function(err, studentAssign) {
if(err) console.log(err);
res.status(200).json(studentAssign);
});
})
So that's the part I am confused at where would I push the 'studentAssign' into 'Assignment' schema's 'studentAssigns array ??
here is my current api json callback:
[
{
"_id": "As 1",
"assignName": "Software Implementation",
"__v": 0,
"studentAssigns": [],
"modInsID": [
{
"_id": 22,
"semester": "TRI 3",
"year": 2016,
"__v": 0,
"modID": [
111
]
}
]
}
]
The documentation just does not make it clear as they just show:
aaron.stories.push(story1);
aaron.save(callback);
With no explanation?
I have attempted:
var assignment = new Assignment();
assignment.studentAssigns.push(studentAssign); and nothing gets stored ??
Here is a working example based on the documentation docs
const mongoose = require('mongoose');
const { Schema } = mongoose;
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);
Person model has its stories field set to an array of ObjectId's
For saving Refs to children you may have first to save stories before pushing them to Person's stories field
const story1 = new Story({
title: 'Casino Royale',
author: author._id // assign the _id from the person
});
story1.save();
And before pushing story1 find the author id you want to push to
const author = await Person.findOne({_id: "624313f302e268b597b8df1f"})
if(Array.isArray(author.stories)) author.stories.push(story1);
author.save()
You model states :
assID: [{ type: Schema.Types.String, ref: 'Assignment' }],
studentID: [{ type: Schema.Types.Number, ref: 'Student' }]
I think from your code you don't want to store multiple assignments in assID and multiple Students in studentID. Modify your model to
assID: { type: Schema.Types.String, ref: 'Assignment' },
studentID: { type: Schema.Types.Number, ref: 'Student' }
Your save code can stay the same.
If you do want to store for example multiple assignments, you need to push them into the assID array ;-)
router.get('/author', (req, res, next) => {
Person.
find().
exec( (err, person) => {
if (err) return handleError(err)
Story.find({author: person[0]._id}).
exec( (err, story) => {
if (err) return handleError(err)
person[0].stories.push(story[0])
res.json( { person: person })
})
})
})

Mongoose one-to-many - not quite sure how to implement it

I'm relatively new to Mongoose (2 days at it) and I want to make a one-to-many relationship, as in one person can come from one country, one country has many people.
So, this is what I've got:
var userSchema = new Schema({
name: String,
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
country: {
type: Schema.Types.ObjectId,
ref: 'Country'
}
});
var User = mongoose.model('Person', userSchema);
var countrySchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
created_at: Date,
updated_at: Date,
people: [{
type: Number,
ref: 'User'
}]
});
var Country = mongoose.model('Country', countrySchema);
var UK = new Country({
name: 'UK'
});
usa.save(function(err) {
var user = new User({
username: 'James',
password: 'Bond',
country: UK._id
});
user.save(function(err) {
});
});
Now I have two questions: 1) I've seen that ref can sometimes be an ObjectId or just a number - what's the differences? 2) when saving the data, in my case, I saved country to a person (by _id), how do I save a person to a country? Should I update the instance of the model?
Thanks
UPDATE:
since this question has been marked as a duplicate, let me rephrase the question: consider the official example in this link: http://mongoosejs.com/docs/populate.html
The idea is that one person has many stories, and one story has one author (person). So, the saving would be as follows:
var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });
aaron.save(function (err) {
if (err) return handleError(err);
var story1 = new Story({
title: "Once upon a timex.",
_creator: aaron._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
});
That's from the official documentation - my question is, where or how do we save story1 to the Author? Author is created before the Story, so, shouldn't the Author be updated with story1._id???
UPDATE 2:
I figured out that if I use only type: Schema.Types.ObjectId and never type: Number, that I can do just this:
var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });
var story1 = new Story({
title: "Once upon a timex.",
_creator: aaron._id // assign the _id from the person
});
aaron.stories.push(story1._id);
aaron.save(function (err) {
if (err) return handleError(err);
});
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
This actually works in a dummy example... are there any problems if there were too many posts in a request that IDs could have get lost/duplicated? What is the shortcoming of this approach?
1) I've seen that ref can sometimes be an ObjectId or just a number - what's the differences?
Please refer to this question Why do they use an ObjectId and a Number in the Mongoose Population example?
where or how do we save story1 to the Author
aaron.save(function (err) {
if (err) return handleError(err);
var story1 = new Story({
title: "Once upon a timex.",
_creator: aaron._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
// save id of story1 into person here, also you should use `update` operation with `$push` operator.
aaron.stories.push(story1._id);
aaron.save(function(err){
if (err)
handleError(err);
else
console.log('save person successfully...');
})
});
});
The results
> db.stories.find()
{ "_id" : ObjectId("56f72f633cf1e6f00159d5e7"), "title" : "Once upon a timex.", "_creator" : 0, "fans" : [ ], "__v" : 0 }
> db.people.find()
{ "_id" : 0, "name" : "Aaron", "age" : 100, "stories" : [ ObjectId("56f72f633cf1e6f00159d5e7") ], "__v" : 1 }

Unable to insert populated document w/ mongoose?

I'm trying to populate a document field with referenced document with the right data and saving it to the database. However, I'm unable to insert a document correctly in the database, even though I had successfully saved the document.
**getting-started.js**
...
var personSchema = mongoose.Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = mongoose.Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
var Johns = new Person({ _id: 15, name: 'Johns', age: 154});
Johns.save(function (err) {
if (err) {
console.log('Person Save error! %s', err);
}
var story1 = new Story({
title: "Once upon a timex??",
_creator: Johns._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
console.log('successful story save! %d', story1._creator);
});
});
Story
.find({ title: 'Once upon a timex######' })
.populate('_creator')
.exec(function (err, story) {
if (err) return handleError(err);
console.log("callback story: ", story);
story.save(function (err, story) {
if (err) return console.error(err);
console.log('successful save new story w/ populated _creator');
console.log('The story: creators name: %s', story._creator.name);
console.log('The story: creator field: %s', story._creator);
})
});
First time executing:
>>node getting-started.js
Following output:
>>opened conn to db
successful story save! 15
opened conn to db
{ fans: [],
__v: 0,
_creator: { stories: [], __v: 0, age: 154, name: 'Johns', _id: 15 },
title: 'Once upon a timex######',
_id: 56244cf796f73380353e803a }
successful save new story w/ populated _creator
The story: creators name: Johns
The story: creator field: { stories: [], __v: 0, age: 154, name: 'Johns', _id: 15 }
However, after commenting out the following code:
var Johns = new Person({ _id: 15, name: 'Johns', age: 154});
Johns.save(function (err) {
if (err) {
console.log('Person Save error! %s', err);
}
var story1 = new Story({
title: "Once upon a timex??",
_creator: Johns._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
console.log('successful story save! %d', story1._creator);
});
});
the next time I'm executing
Story
.find({ title: 'Once upon a timex######' })
.exec(function (err, story) {
if (err) return handleError(err);
console.log("callback story: ", story);
});
I'm unable to see my saved Story with the populated field of _creator, it still only has the person _id and not the person object:
{ fans: [],
__v: 0,
_creator: 15,
title: 'Once upon a timex######'
_id: 56244cf796f73380353e803a }

mongoose populate not populating an array

I am facing an issue where mongoose query is not populating an array type.
Here is institute schema
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var InstituteSchema = new Schema({
name: String,
address: String,
city: String,
country: String,
zip: String,
owner: { type: mongoose.Schema.ObjectId, ref: 'User' },
teachers: [{type: mongoose.Schema.ObjectId, ref: 'Teacher'}],
categories: [String],
created : { type : Date, default : Date.now }
});
module.exports = mongoose.model('Institute', InstituteSchema);
And here is teacher Schema
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TeacherSchema = new Schema({
education: [{degree: String, instituteName: String}],
dob: Date,
photoUrl: String,
phoneNumber: String,
owner: {type: mongoose.Schema.ObjectId, ref: 'User'},
institutes: [{type: mongoose.Schema.ObjectId, ref: 'Institute'}],
subjects: [{type: mongoose.Schema.ObjectId, ref: 'Subject'}],
created : { type : Date, default : Date.now }
})
module.exports = mongoose.model('Teacher', TeacherSchema);
Here is a method which queries the institute by owner id
exports.mine = function (req, res, next) {
var ObjectId = mongoose.Types.ObjectId;
var userId = new ObjectId(req.user._id);
Institute.find({
owner: userId
}).populate('teachers').exec(function (err, institute) {
if (err) return next(err);
if (!institute) return res.json(401);
res.json(institute);
});
};
I can see from the db that institute has teacher added
db.institutes.find();
{
"_id" : ObjectId("554719a9f5be11c6d4369264"),
"owner" : ObjectId("5547199bf5be11c6d4369263"),
"country" : "USA",
"name" : "Raghvendra Singh",
"address" : "38589 Royal Ann Cmn",
"city" : "Fremont",
"zip" : "94536",
"created" : ISODate("2015-05-04T07:03:05.569Z"),
"categories" : [ "IIT", "Medical" ],
"teachers" : [ ObjectId("55471965f5be11c6d436925f") ],
"__v" : 3
}
But somehow the query method doesn't populate the teachers collection. The weird thing is that i don't even get the collection with object ids and it returns and institute with empty teacher array.
And when i remove the .populate('teachers') from the method call it indeed returns the teacher array with object ids.
I looked at the documentation and i can't see what am i doing wrong.
First you need to change your Model slightly as mention for teachers feild.
teachers: [ { teacher: { type: Schema.ObjectId, ref: "Teacher" } } ]
exports.mine = function (req, res, next) {
var ObjectId = mongoose.Types.ObjectId;
var userId = new ObjectId(req.user._id);
Institute.find({
owner: userId
}).populate('**teachers.teacher**').exec(function (err, institute) {
if (err) return next(err);
if (!institute) return res.json(401);
res.json(institute);
});
};
Then, change your populate parameter to teachers.teacher . It will work

MissingSchemaError: Schema hasn't been registered for model "Users" when populate

I write model for create User and following and followers
var UserSchema = new Schema({
created_at : { type: Date, default: Date.now }
, name : String
, hashedPass : String
, salt: String
, email : Email
, avatar : {type: String, default: "images/default_profile.png" }
, statuses_count : Number
, screen_name : String
, location : String
, about : String
, followers: [{ type: ObjectId, ref: 'Users' }]
, following: [{ type: ObjectId, ref: 'Users' }]
, followers_count : Number
, following_count : Number
});
and in create follow in user I do
UserSchema.statics.createFollowing = function(data, callback) {
console.log("data: ", data);
this.findOne({
name : data.name
}, function(err, docs) {
if (err)
callback("error " + err)
else if (docs) {
docs.following.push({"_id" : data.name_follow});
docs.save(function(err) {
if (err)
callback(err);
console.log("___cxxx_____", this);
mongoose.model('User').findOne({
_id : docs._id
}).populate('following', 'name screen_name avatar').exec(function(err, docs) {
if (err)
callback(err);
console.log('The creator is %s', docs.following)
callback(docs);
});
});
}
});
}
when I request Like this
http://localhost:3000/auth/createfollowing?callback=jQuery16104670869295950979_1361607659796&{"name":"testuser1","name_follow":"envatowebdev","token":"ece20af054339bb52d4feee9a05ab8cc401f8dec6b622b8df1e4c0d1789825bee8dd47f572cdc737a098a5be03044596","device":"xphone"}&_=1361607667778
I return like that
Mongoose: users.findOne({ _id: ObjectId("5128781fcb8c95909c00000e") }) { fields: undefined, safe: undefined }
/data/workspace/node/serverjs/node_modules/mongoose/lib/utils.js:397
throw err;
^
MissingSchemaError: Schema hasn't been registered for model "Users".
Use mongoose.model(name, schema)
at NativeConnection.Connection.model (/data/workspace/node/serverjs/node_modules/mongoose/lib/connection.js:597:11)
at model.populate [as _populate] (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:150:23)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:269:14)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at next (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:232:57)
at init (/data/workspace/node/serverjs/node_modules/mongoose/lib/model.js:215:12)
I don't know why it like that and how to populate following and followers.
Thank in advance
problem is Here model is User but I assigned Users
followers: [{ type: ObjectId, ref: 'Users' }]
For those of you using MEAN.js, #sepdau was correct, but you have to add just one more thing. For example, if you want to create a model that has a field that is an array of Unicorns, this would be the correct syntax:
var StackOverflowSchema = new Schema({
title: {
type: String,
default: 'StackOverflow',
trim: true,
required: 'Name cannot be blank'
},
unicorns: [{ type: Schema.ObjectId, ref: 'Unicorn' }]
});

Resources