You need to have a separate examination collection for this.
(It is like the intermediate (associative) table in relational databases.)
One way to solve this is using virtual populate.
With virtual populate we don't need to keep references to the examinations, which will simplify things when an examination is added, updated or deleted.
Because only the examinations collection will need to be updated.
patient.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);
examination.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);
As you see our patient and hospital schemas are very clean without any examination reference.
Let's have these existing patients.
{
"_id" : ObjectId("5e0f86d0ea3eb831a4845064"),
"name" : "Patient 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f86dbea3eb831a4845065"),
"name" : "Patient 2",
"__v" : NumberInt(0)
}
Let's have these existing hospitals.
{
"_id" : ObjectId("5e0f86feea3eb831a4845066"),
"name" : "Hospital 1",
"__v" : NumberInt(0)
},
{
"_id" : ObjectId("5e0f8705ea3eb831a4845067"),
"name" : "Hospital 2",
"__v" : NumberInt(0)
}
Let's have these existing examinations.
/* 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
}
Now if we want to get the info of a patient and his/her examinations we can use the following code:
app.get("/patients/:id", async (req, res) => {
const result = await Patient.findById(req.params.id).populate("examinations");
res.send(result);
});
The result will be like this:
{
"_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"
}
We can even populate the hospital like this with an inner populate:
app.get("/patients/:id", async (req, res) => {
const result = await Patient.findById(req.params.id).populate({
path: "examinations",
populate: {
path: "hospitalId"
}
});
res.send(result);
});
The result will contain the hospital info:
{
"_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"
}
Now with this knowledge you can yourself implement the retrieve operations from the hospital side.