Mongoose: Referencing a subdocument from another subdocument AND population - node.js

I have a document model called school which in turn has two subdocuments:
students
class
Each student belongs to one class.
var classSchema = new Schema({
name: {type : String}
});
var studentSchema = new Schema({
name : {type : String, required:true},
class: { type: ObjectId, ref: 'Institute.classes' },
});
var schoolSchema = new Schema({
name : {type : String, required:true},
students : [studentSchema],
classes : [classSchema]
});
var School = mongoose.model('School', schoolSchema);
Now when I am fetching a student, I want to populate the class as well. I am doing this as:
var school_id = req.params.school_id;
var student_id = req.params.student_id;
School
.findOne({'_id': school_id, 'students._id': student_id})
.populate({path: 'students.class'})
.exec(function (err, data) {
done(err, data);
});
When I do this, I get following error:
"message": "Schema hasn't been registered for model \"School.classes\".\nUse mongoose.model(name, schema)",
"name": "MissingSchemaError"
Is is possible to populate a subdocument from another subdocument?
Any help is appreciated. Thanks :)

Related

Is it possible to design such schema in MongoDB ? If not any suggestions?

I am trying to develop such a schema in MongoDB.
var subCategorySchema = new Schema({
_id: ObjectId,
name : String,
});
var categorySchema = new Schema({
name : String,
category : {
type : Schema.Types.ObjectId,
ref : 'subCategories'
},
});
var postSchema = new Schema({
name : String,
category : {
type : Schema.Types.ObjectId,
ref : 'categories'
},
subCategory : {
type : Schema.Types.ObjectId,
ref : 'categories'
}
});
The issue is that how can I directly populate sub category in post ?

Mongoose Model ObjectId References Not Working

I'm working with Mongoose models and references. I've been using the code from mongoose's website where it talks about the populate method and references. I am trying to have it save the respective "referenced" ids in both models. It is only saving the reference ids in the story model. Here is the code:
Update: Added schemas at the top to help:
var personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
(end of schemas)
var author = new Person({
_id: new mongoose.Types.ObjectId(),
name: 'Ian Fleming',
age: 50
});
author.save(function (err) {
if (err) return handleError(err);
var story1 = new Story({
title: 'Casino Royale',
author: author._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
});
When you run this code, it generates this in mongo:
db.people.find()
{ "_id" : ObjectId("5be0a37f1dd61a343115e2c8"), "stories" : [ ], "name" : "Ian Fleming", "age" : 50, "__v" : 0 }
db.stories.find()
{ "_id" : ObjectId("5be0a37f1dd61a343115e2c9"), "title" : "Casino Royale", "author" : ObjectId("5be0a37f1dd61a343115e2c8"), "__v" : 0 }
It appears to not be storing any ids in the people collection within "stories." Wouldn't you want to save the stories ids in the people collection as well?
I tried to modify the code to make it work with (moved the author save function, until after the story id is set):
var author = new Person({
_id: new mongoose.Types.ObjectId(),
name: 'Ian Fleming',
age: 50
});
var story1 = new Story({
_id: new mongoose.Types.ObjectId(),
title: 'Casino Royale',
author: author._id // assign the _id from the person
});
author.stories = story1._id;
author.save(function (err) {
if (err) return handleError(err);
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
This gives me an author undefined.
Mongo wouldn't automatically add to the Person "stories" field just because you added a Story object.
You don't really need to store the story ids in Person objects anyway, as you can always get a list of stories by an author with
db.stories.find({author: <id>})
Storing in both places would create redundant information and you'd have to pick one to be the truth in the case of a mismatch. Better to not duplicate, methinks.
UPDATE:
References appear to help you populate referenced fields in queries automatically. According to this post you can retrieve an author and their stories like this:
db.persons.find({_id: <id>}).populate('stories')
Haven't personally used this but it looks pretty handy.
Mongoose docs for populate: https://mongoosejs.com/docs/populate.html

How to find in mongoose with deep population?

I succeed to make a deep population with find and the search key in first model, but now i want to find by key on the sub object generated by the deep populate.
I have three models : Product, Category, and Event
I want to find my Products by e_fk_club_id that is in Event model
I tried two solutions but they didn't work
First solution in find :
model.find({'categories.events.e_fk_club_id':id})`
Second solution with match :
`$match : { e_fk_club_id : id }`
these are my models
product.js
var ProductSchema = new mongoose.Schema({
p_id: Number,
p_name: String,
p_fk_category: {type: mongoose.Schema.Types.ObjectId, ref: 'categories'},
}
, {collection: 'products'});
module.exports = mongoose.model('products', ProductSchema);
Category.js
var CategorySchema = new mongoose.Schema({
c_id: Number,
c_name: String,
c_fk_event: {type: mongoose.Schema.Types.ObjectId, ref: 'events'},
}
, {collection: 'categories'});
module.exports = mongoose.model('categories', CategorySchema);
Event.js
var EventSchema = new mongoose.Schema({
e_id: Number,
e_name: String,
e_fk_club_id: Number,
}
, {collection: 'events'});
module.exports = mongoose.model('events', EventSchema);
This is the code which i am trying to fetch the data :
getProductsByClub:function (id, callback){
var model = require("Product");
//model
model .find({'categories.events.e_fk_club_id':id})
.populate({
path:'p_fk_category',
model:'categories',
populate:
{
path:'e_fk_event',
model:'events',
//$match : { e_fk_club_id : id }
}
})
.exec (function(err, doc){
if (err) {
callback(err) ;
} else {
callback(doc) ;
}
})
},
Is There any solution.
Thank you in advance.

Mongo: query on subdocs

Hello I have this problem when checking if a subdocument exist before pushing a new subdocument.
var UserSchema = new Schema({
name : String,
app_key : String,
app_secret : String,
tasks : [{type: Schema.ObjectId, ref: 'Task'}] // assuming you name your model Task
});
var TaskSchema = new Schema({
name : String,
lastPerformed : Date,
folder : String,
user : {type: Schema.ObjectId, ref: 'User'} // assuming you name your model User
});
With this, your query for all users, including arrays of their tasks might be:
User.findOne({...}).populate('tasks').run(function(err, user) {
var subdoc = user.tasks.id(mytask.id);
if(subdoc){
//not exist
//push
}
});
This is the error:
TypeError: Object has no method 'id'
You are getting that error because there is no 'id' field defined for the 'tasks' subdocument. You might have meant 'user.tasks._id', which will return the ObjectId that MongoDB adds to its documents by default.

How to update in mongoose?

I am new at Mongoose/nodejs and I am struggling with a simple update of an array within an array.
Here's the schema:
var County = new Schema({
_id : Schema.ObjectId,
name : String,
biggestCity : String
});
var Country = new Schema({
_id : Schema.ObjectId,
name : String,
counties : {type: [County], ref: "County"}
});
var Continent = new Schema({
_id : Schema.ObjectId,
countries : {type: [Country], ref: "Country"},
});
And here's the update code I've been trying:
var continents = mongoose.model("Continent");
var update = { "countries.counties.name": newName, "countries.counties.biggestCity": newBiggestCity };
var conditions = { "_id": countryId, "countries.name": countryName, "countries.counties.name": countyName };
var options = { multi: false };
wagers.update(conditions, update, options, function(err, numAffected) {
//callback code...
});
When doing this, the error in err says "Can't append to array using string field name 'counties'". What does this mean? What am I doing wrong?
You should define the child object as another Schema, not just as a list of some anonymous object. (Reference.)
Try defining Country as a separate Schema, nest that in Continent, then do your update.

Resources