È necessario disporre di una raccolta di esami separata per questo. (È come la tabella intermedia (associativa) nei database relazionali.)
Un modo per risolvere questo problema è utilizzare il popolamento virtuale. Con il popolamento virtuale non è necessario mantenere i riferimenti agli esami, il che semplificherà le cose quando un esame viene aggiunto, aggiornato o eliminato. Perché solo la raccolta degli esami dovrà essere aggiornata.
paziente.js
const mongoose = require("mongoose");
const patientSchema = new mongoose.Schema(
{
name: String
},
{
toJSON: { virtuals: true }
}
);
// Virtual populate
patientSchema.virtual("examinations", {
ref: "Examination",
foreignField: "patientId",
localField: "_id"
});
module.exports = mongoose.model("Patient", patientSchema);
hospital.js
const mongoose = require("mongoose");
const hospitalSchema = new mongoose.Schema(
{
name: String
},
{
toJSON: { virtuals: true }
}
);
// Virtual populate
hospitalSchema.virtual("examinations", {
ref: "Examination",
foreignField: "hospitalId",
localField: "_id"
});
module.exports = mongoose.model("Hospital", hospitalSchema);
esame.js
const mongoose = require("mongoose");
const examinationSchema = new mongoose.Schema({
when: {
type: Date,
default: Date.now()
},
patientId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Patient"
},
hospitalId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Hospital"
}
});
module.exports = mongoose.model("Examination", examinationSchema);
Come vedete, i nostri schemi paziente e ospedaliero sono molto puliti senza alcun riferimento all'esame.
Prendiamo questi pazienti esistenti.
{
"_id" : ObjectId("5e0f86d0ea3eb831a4845064"),
"name" : "Patient 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f86dbea3eb831a4845065"),
"name" : "Patient 2",
"__v" : NumberInt(0)
}
Prendiamo questi ospedali esistenti.
{
"_id" : ObjectId("5e0f86feea3eb831a4845066"),
"name" : "Hospital 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f8705ea3eb831a4845067"),
"name" : "Hospital 2",
"__v" : NumberInt(0)
}
Facciamo questi esami esistenti.
/* Patient 1 - Hospital 1 */
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f878346e50d41d846d482",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f86feea3eb831a4845066",
"__v": 0
},
/* Patient 1 - Hospital 1 */
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87a646e50d41d846d483",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f86feea3eb831a4845066",
"__v": 0
},
/* Patient 1 - Hospital 2*/
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87c446e50d41d846d484",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f8705ea3eb831a4845067",
"__v": 0
},
/* Patient 2 - Hospital 1 */
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87e046e50d41d846d485",
"patientId": "5e0f86dbea3eb831a4845065",
"hospitalId": "5e0f86feea3eb831a4845066",
"__v": 0
}
Ora se vogliamo ottenere le informazioni di un paziente e dei suoi esami possiamo utilizzare il seguente codice:
app.get("/patients/:id", async (req, res) => {
const result = await Patient.findById(req.params.id).populate("examinations");
res.send(result);
});
Il risultato sarà questo:
{
"_id": "5e0f86d0ea3eb831a4845064",
"name": "Patient 1",
"__v": 0,
"examinations": [
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f878346e50d41d846d482",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f86feea3eb831a4845066",
"__v": 0
},
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87a646e50d41d846d483",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f86feea3eb831a4845066",
"__v": 0
},
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87c446e50d41d846d484",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": "5e0f8705ea3eb831a4845067",
"__v": 0
}
],
"id": "5e0f86d0ea3eb831a4845064"
}
Possiamo anche popolare l'ospedale in questo modo con una popolazione interna:
app.get("/patients/:id", async (req, res) => {
const result = await Patient.findById(req.params.id).populate({
path: "examinations",
populate: {
path: "hospitalId"
}
});
res.send(result);
});
Il risultato conterrà le informazioni sull'ospedale:
{
"_id": "5e0f86d0ea3eb831a4845064",
"name": "Patient 1",
"__v": 0,
"examinations": [
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f878346e50d41d846d482",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": {
"_id": "5e0f86feea3eb831a4845066",
"name": "Hospital 1",
"__v": 0,
"id": "5e0f86feea3eb831a4845066"
},
"__v": 0
},
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87a646e50d41d846d483",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": {
"_id": "5e0f86feea3eb831a4845066",
"name": "Hospital 1",
"__v": 0,
"id": "5e0f86feea3eb831a4845066"
},
"__v": 0
},
{
"when": "2020-01-03T18:27:12.997Z",
"_id": "5e0f87c446e50d41d846d484",
"patientId": "5e0f86d0ea3eb831a4845064",
"hospitalId": {
"_id": "5e0f8705ea3eb831a4845067",
"name": "Hospital 2",
"__v": 0,
"id": "5e0f8705ea3eb831a4845067"
},
"__v": 0
}
],
"id": "5e0f86d0ea3eb831a4845064"
}
Ora con queste conoscenze puoi implementare tu stesso le operazioni di recupero dal lato ospedaliero.