Você precisa ter uma coleção de exames separada para isso. (É como a tabela intermediária (associativa) em bancos de dados relacionais.)
Uma forma de resolver isso é usando o preenchimento virtual. Com o preenchimento virtual não precisamos manter referências aos exames, o que simplificará quando um exame for adicionado, atualizado ou excluído. Porque apenas a coleção de exames precisará ser atualizada.
paciente.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);
exam.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);
Como você vê, nossos esquemas de pacientes e hospitais são muito limpos, sem qualquer referência de exame.
Vamos ter esses pacientes existentes.
{
"_id" : ObjectId("5e0f86d0ea3eb831a4845064"),
"name" : "Patient 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f86dbea3eb831a4845065"),
"name" : "Patient 2",
"__v" : NumberInt(0)
}
Vamos ter esses hospitais existentes.
{
"_id" : ObjectId("5e0f86feea3eb831a4845066"),
"name" : "Hospital 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f8705ea3eb831a4845067"),
"name" : "Hospital 2",
"__v" : NumberInt(0)
}
Vamos ter esses exames existentes.
/* 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
}
Agora, se quisermos obter as informações de um paciente e seus exames, podemos usar o seguinte código:
app.get("/patients/:id", async (req, res) => {
const result = await Patient.findById(req.params.id).populate("examinations");
res.send(result);
});
O resultado será assim:
{
"_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"
}
Podemos até preencher o hospital assim com uma população 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);
});
O resultado conterá as informações do hospital:
{
"_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"
}
Agora, com esse conhecimento, você mesmo pode implementar as operações de recuperação do lado do hospital.