I have the following models in node js and i want to get data from file schema and from client schema in just one call, i was reading about populate but have no ideia how to use that.
This is my model
const mongoose = require('mongoose');
const fileSchema = mongoose.Schema({
_id: mongoose.SchemaTypes.ObjectId,
client_id: mongoose.SchemaTypes.ObjectId,
user_id: mongoose.SchemaTypes.ObjectId,
status: String,
name: String,
path: String,
clients: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Client' }]
});
const clientSchema = mongoose.Schema({
_id: mongoose.SchemaTypes.ObjectId,
name: String,
img: String
});
module.exports =
mongoose.model('File', fileSchema, 'files'),
Client = mongoose.model('Client', clientSchema, 'clientes');
This is how i am getting the file data now
exports.getFiles = (req, res, next) => {
File.find({ field: res.locals.field })
.select('_id client_id user_id status name path')
.exec()
.then(file => {
res.status(200).json({
response: file
});
})
.catch(err => {
console.log(err);
res.status('500').json({
error: err
});
});
};
this returns an json response, when i tried to use populate i got an empty array.
You're almost there but you have an issue with your find search. At least with the File model you posted, you don't have a field called 'field' so you won't get any results.
Let's pretend that you're trying to find a file based off of its name and the request is being sent to the url 'blah/files/:name' and it looks like you're using Express.js so this should work.
To use populate, you usually do something like:
File.find({ name: req.params.name })
.populate('clients')
.exec()
.then(files => {
res.status(200).json({
response: files
});
})
.catch(err => {
console.log(err);
res.status('500').json({
error: err
});
});
What you have in your 'select' bit it not necessary since you're starting the search based on the File model and you're just asking it to return all of the fields you have anyway on that model. You get those returned in the result 'for free'.
The populate is flagged out on the 'clients' field since you specified in the File model that it's an object id that references the Client model. Mongoose should handle it basically automagically. However, be careful, ALL of the fields on the Client model will be populated in the clients array of the File. If you want to return only one or a couple fields for your clients, it's there that you should use the select.
Also a note: the find method will return an array even if it's just a result of one document. If you are expecting or wanting just one result, use the findOne method instead.
Update
It looks like there's also a bugaboo in your module exports in the model file, which could be why you are having problems. My coding style is different from yours but here's how I would do it just to be sure that there are no mess ups :
const File = mongoose.model('File', fileSchema);
const Client = mongoose.model('Client', clientSchema);
module.exports = { File, Client };
Then in your router code, you import them as so:
const { File, Client } = require('<path-to-model-file>');