sql >> Base de Datos >  >> NoSQL >> MongoDB

Necesita consejos para diseñar una base de datos en mongodb con mongoose

Necesita tener una colección de exámenes separada para esto. (Es como la tabla intermedia (asociativa) en las bases de datos relacionales).

Una forma de resolver esto es usar la población virtual. Con la población virtual no necesitamos mantener referencias a los exámenes, lo que simplificará las cosas cuando se agregue, actualice o elimine un examen. Porque solo será necesario actualizar la colección de exámenes.

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);

examen.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 puede ver, nuestros esquemas de pacientes y hospitales están muy limpios sin ninguna referencia de examen.

Tengamos estos pacientes existentes.

{
    "_id" : ObjectId("5e0f86d0ea3eb831a4845064"),
    "name" : "Patient 1",
    "__v" : NumberInt(0)
},
{
    "_id" : ObjectId("5e0f86dbea3eb831a4845065"),
    "name" : "Patient 2",
    "__v" : NumberInt(0)
}

Tengamos estos hospitales existentes.

{
    "_id" : ObjectId("5e0f86feea3eb831a4845066"),
    "name" : "Hospital 1",
    "__v" : NumberInt(0)
},
{
    "_id" : ObjectId("5e0f8705ea3eb831a4845067"),
    "name" : "Hospital 2",
    "__v" : NumberInt(0)
}

Tengamos estos exámenes 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
}

Ahora bien, si queremos obtener la información de un paciente y sus exámenes, podemos usar el siguiente código:

app.get("/patients/:id", async (req, res) => {
  const result = await Patient.findById(req.params.id).populate("examinations");
  res.send(result);
});

El resultado será así:

{
    "_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"
}

Incluso podemos poblar el hospital de esta manera con una población 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);
});

El resultado contendrá la información del 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"
}

Ahora, con este conocimiento, usted mismo puede implementar las operaciones de recuperación desde el lado del hospital.