Need advice to design database in mongodb with mongoose

后端 未结 2 1466
独厮守ぢ
独厮守ぢ 2020-12-12 06:04

I have 2 collections: Hospital and Patient. This month the patient is examination at hospital A, But next month, this patient is examination at hospital B. So when updating

相关标签:
2条回答
  • 2020-12-12 06:34

    Mongodb does not allow specific joins like a sql based db. I would recommend creating a your hospital collection schema as needed (most likely just basic types such as strings and numbers) and then store a list of visits or examinations with the date and location as part of your patient schema (see: https://mongoosejs.com/docs/schematypes.html#arrays). While you cannot enforce at a database level that the examination location is a valid hospital, you could certainly enforce this in your code.

    0 讨论(0)
  • 2020-12-12 06:49

    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.

    0 讨论(0)
提交回复
热议问题