Thursday 20 September 2018

Mongoose: how to populate nested schemas with cross-references?

Hi guys,I am building a webapp for learning purposes with NodeJS and Mongo (Mongoose). It should be a Job Board that allows users (HR managers) to keep track of the job openings and the candidates. I am probably creating too much confusion with Mongoose Schema so I'd be happy to find some suggestion.I have 3 Schema for:- Company- Position- CandidateThese are the working cross-references amongst them (using mongoose.Schema.Types.ObjectId):- each Company has a property that includes the array of open positions for that companyname: String, logUrl: String, positions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Position' }] - each Position has a reference to its own companyrole: String, salary: Number, jobDescription: String, company: { type: mongoose.Schema.Types.ObjectId, ref: 'Company' } - each Position has also an array of candidates that applied... candidates: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Candidate' }] - each Candidate has an array of positions (a single candidate can apply to multiple positions).name: String, surname: String, email: String, positions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Position' }] Using .populate( ) I am able to manage all of them and access specific properties of linked objects. In this example, I can open the profile of a candidate, read the list of positions he applied and display the logo of the companies that have those openings. In this other example, I can open the profile of a company, read the list of openings and see the number of candidates for each one of them.​So far so good, everything works as expected ✌️​Now my goal is to add two properties to the array of positions in the Candidate schema than can keep track of the status of that application and the notes taken by the HR manager: the output should be similar to this.My Candidate schema is now:name: String, surname: String, email: String, positions: [ { detail: { type: mongoose.Schema.Types.ObjectId, ref: 'Position' }, progress: { type: String }, // keep track of the status comment: { type: String } // keep track of internal notes }], My code for opening and populating the candidate's page is:app.get('/:id', (req, res) => { Candidate .findById(req.params.id) .populate({ path: 'positions.detail', model: Position, populate: { path: 'company', model: Company } }) .exec(function (err, foundCandidate) { if (err) { console.log(err) } else { res.render('candidates/show', {candidate: foundCandidate}) } }) }) Now the problem: positions.detail is not getting populated. With the previous Schema (and without these two new properties), I was able to easily retrieve data on the position with position.property as well as on the company with position.company.property; now I am using position.detail.property and position.detail.company.property but they don't work: Cannot read property 'property' of undefinedCan anyone help me with this?

Submitted September 20, 2018 at 06:49PM by kuro1988

No comments:

Post a Comment