Goal: Get the students based on the given library name. The student model has the library name linked in the database.
What's happening: 1: Retrieving the name that is linked to the given ID (library ID aquired with useParams().id). 2: Looking for all students based on that found library name.
Result: Empty response. I feel like the problem has to do with the line library_name = library.name;
. Simply that value hasn't set yet when the second query starts to execute? Because when I log the result right after this line, with res.send(library_name);
the name is showing correctly.
app.get("/students/:id", (req, res) => {
const id = req.params.id;
let library_name = "";
LibraryModel.findById(id, (err, library) => {
library_name = library.name;
});
StudentModel.find({library: library_name}, (err, students) => {
if (err) {
res.send(err);
} else {
res.send(students);
}
});
});
CodePudding user response:
You are right. library_name
gehts only set in the callback function you passed, which happens after the StudentModel.find(...)
gets called. Basically you are currently performing these 2 calls in parallel.
There are three ways to resolve this issue.
Moving second call to callback function
app.get("/students/:id", (req, res) => {
const id = req.params.id;
let library_name = "";
LibraryModel.findById(id, (err, library) => {
library_name = library.name;
StudentModel.find({library: library_name}, (err, students) => {
if (err) {
res.send(err);
} else {
res.send(students);
}
});
});
});
Use promises To avoid what's known as "callback hell" can you also use promises instead of callback functions and await them:
app.get("/students/:id", async (req, res) => {
const id = req.params.id;
try {
const library = await LibraryModel.findById(id);
const students = await StudentModel.find({library: library.name});
res.send(students);
} catch (err) {
res.send(err);
}
});
Use a single aggregation pipeline
You can also merge these two separate databases queries into a single aggregation pipeline. You would need to first use $lookup
and afterwards use $match to filter for the specific entries. Nevertheless there is additional information on the schemas needed in order to build this query.
Another Hint I assume you are trying to create a RESTful API. You might want to review your path structure, since a RESTful approach would expect the ':id' to be the ID of a student, not the ID of a library. It looks like GET '/libraries/:id/students' makes more sense in your case.