Skip to content

Модель данных

10023r edited this page Nov 15, 2023 · 8 revisions

Нереляционная модель

Графическое представление

patient {

_id: ObjectID,
prof_info: {
    email: String,
    password: String,
},
card: {
    name: String,
    surname: String,
    birthdate: Date (dd/mm/yyyy),
    contact: String,
    bloodGroup: String
},

images: [
    {
        date: Date (dd/mm/yyyy),
        name: String,
        img: BinaryData
    }
]

}


doctor {

_id: ObjectID,
name: String,
surname: String,
email: String,
password: String,
contact: String,
experience: String

}


history: {

date: Date (hh:min, dd/mm/yyyy),
procedure: {
    name: String,
    price: Double
},
patientCard: {
    name: String,
    surname: String,
    birthdate: Date (dd/mm/yyyy),
    contact: String,
    bloodGroup: String
}

doctor: {
    name: String, 
    surname: String
},
helped: {
    rate: String,
    feedback: String
}

}


appointments {

_id: ObjectID,

date: Date (hh:min, dd/mm/yyyy), 

procedure: {
    name: String,
    price: Double
},

patientCard: {
    name: String,
    surname: String,
    birthdate: Date (dd/mm/yyyy),
    contact: String,
    bloodGroup: String
}

doctor: {
    name: String,
    surname: String
}

}


administrator {

_id: ObjectID,
name: String,
surname: String,
email: String,
password: String

}


equipment {

_id: ObjectID,
name: String,
lastService: Date (dd/mm/yyyy),
status: String

}


serviceRequest {

_id: ObjectID,
equipmentID: ObjectID,
requesterID: ObjectID,
description: String,
requestDate: Date (dd/mm/yyyy)

}


statistic {

_id: ObjectID,
date: Date,
val: Double

}


procedure {

_id: ObjectID,
name: String,
price: Double

}

Описание назначений коллекций, типов данных и сущностей

БД содержит следующие коллекции:

patient - коллекиция, для хранения данных пациентов.

  • _id - уникальный идентификатор пациента;
  • prof_info - информация о профиле
    • email - почта
    • password - пароль
  • card - мед. карта пациента
    • name - имя пациента
    • surname - фамилия пациента
    • birthdate - дата рождения
    • contact - контактный телефон
    • bloodGroup - группа крови пациента
  • images - список снимков пациента
    • date - датя снятия снимка
    • name- название снимка
    • img - сам снимок в в бинарном виде

doctor - коллекция, для хранения данных докторов.

  • _id - уникиальный идентификатор доктора
  • name - имя
  • surname - фамилия
  • email - почта
  • password - пароль
  • contact - контактный телефон
  • experience - стаж


history - коллекция для хранения истории лечений

  • _id - ID записи в истории
  • date - дата лечения
  • procedure - объект хранящий информацию о процедуре
    • name - название
    • price - цена
  • patientCard - медкарта пациента
    • name - имя
    • surname - фамилия
    • birthdate - дата рождения
    • contact - контактный телефон
    • bloodGroup - группа крови пациента
  • doctor - информация о докторе, лечившем пациента
    • name - имя
    • surname - фамилия
  • helped - отзыв пациента
    • rate - оценка
    • feedback - текст отзыва


appointments - коллекция для хранения предстоящих встреч.

  • _id - уникальный идентификатор
  • date - дата и время встречи
  • procedure - процедура
  • patientCard - данные пациента, который записался на эту встречу
    • name - имя пациента
    • surname - фамилия
    • birthdate - возраст
    • contact - контактный телефон
    • bloodGroup - группа крови
  • doctor - данные о докторе, который назначен на эту встречу
    • name - имя доктора
    • surname - фамилия


administrator - коллекция, для хранения администраторов. В этой коллекции хранятся данные об аккаунте администратора.

  • _id - уникальный идентификатор аккаунта админа
  • name - имя;
  • surname - фамилия;
  • email - эл. почта;
  • password - пароль;


equipment - коллекция, для хранения оборудований клиники.

  • _id - уникальный идентификатор оборудования
  • name - название оборудования;
  • lastService - дата последнего обслуживания;
  • status - статус (используется, в починке);


serviceRequest - коллекция, для хранения запросов на ремонт оборудования.

  • _id - уникальный идентификатор запроса на ремонт
  • equipemntID - ID оборудования
  • requesterID - тот, кто оставил заявку
  • description - краткое описание заявки и/или причина
  • requestDate - дата создания запроса на ремонт;


statistic - коллекция для хранения статистики

  • _id - уникальный идентификатор операции
  • date - дата совершения операции
  • val - сумма (положительная или отрицательная)


procedure - коллекция для хранения доступных процедур/услуг клиники

  • _id - уникальный идентификатор процедуры
  • name - название,
  • price - цена

Оценка объема информации, хранимой в модели

Коллекция patient. Допустим, что у каждого пациента в среднем 3 снимка и 5 записей в истории посещений. Тогда, для хранния x пациентов понадобится:

$$ x*(12 + 42 + 52 + 3*5000000) = 15000106x $$

  • _id - тип ObjectID V = 12 байт
  • prof_info - тип Object V = 30 + 12 = 42
    • email - String V = 30 байт
    • password - String V = 12 байт
  • card - тип Object V = 15 + 15 + 8 + 12 + 2 = 52 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт
    • birthdate - Date V = 8 байт
    • contact - String V = 12 байт
    • bloodGroup - String V = 2 байта
  • images - Array V_i = 8 + 20 + 5000000 = 5 МБайт
    • date - Date V = 8 байт
    • name - String V = 20 байт
    • img - Binary Data (допустим, что средний размер снимка 5 Мб) V = 5 МБайт


Коллекция doctor. Пусть на каждые 10 пациентов приходится 1 доктор. Тогда:

$$ (x/10 + 1)*(12 + 94) = 106 * (x/10 + 1) = 106 + 68.6x = 106 + 69x $$

  • _id - ObjectID V = 12 байт
  • info - Object V = 15 + 15 + 30 + 12 + 12 + 10 = 94 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт
    • email - String V = 30 байт
    • password - String V = 12 байт
    • contact - String V = 12 байт
    • experience - String V = 10 байт


Коллекция history. Пусть в среднем на каждого пациента 5 записей. Тогда:

$$ V(x) = 5x(12 + 8 + 28 + 52 + 30 + 51) = 675x $$

  • _id - ObjectID V = 12 байт
  • date - Date V = 8 байт
  • procedure - Object V = 20 + 8 = 28 байт
    • String V = 20 байт,
    • Double V = 8 байт
  • patientCard - Object V = 15 + 15 + 8 + 12 + 2 = 52 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт
    • birthdate - Date V = 8 байт
    • contact - String V = 12 байт
    • bloodGroup - String V = 2 байта
  • doctor - Object V = 15 + 15 = 30 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт
  • helped - Object V = 1 + 50 = 51 байт
    • rate - String V = 1 байт
    • feedback - String V = 50 байт


Коллекция appointments. Пусть в среднем приходится 10 записей на каждого пациента x. Тогда

$$ 10x*(12 + 8 + 20 + 58 + 30) = 1280x $$

  • _id - ObjectID V = 12 байт
  • date - Date V = 8 байт
  • procedure - String V = 20 байт
  • patient - Object V = 15 + 15 + 8 + 12 + 6 + 2 = 58 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт
    • birthdate - Date V = 8 байт
    • contact - String V = 12 байт
    • patientCard - String V = 6 байт
    • bloodGroup - V = 2 байта
  • doctor - Object V = 15 + 15 = 30 байт
    • name - String V = 15 байт
    • surname - String V = 15 байт


Коллекция administrator. Пусть в среднем 1 аккаунт администратора. Тогда:

$$ 12 + 15 + 15 + 30 + 12 = 84 $$

  • _id - ObjectID V = 12 байт
  • name - String V = 15 байт
  • surname - String V = 15 байт
  • email - String V = 30 байт
  • password - String V = 12 байт


Коллекция equipment. Пусть в среднем 20 оборудований в клинике. Тогда:

$$ 20*(12 + 50 + 8 + 2) = 1440 $$

  • _id - ObjectID V = 12 байт
  • name - String V = 50 байт
  • lastService - Date V = 8 байт
  • status - Boolean V = 2 байта


Коллекция serviceRequest. Пусть в среднем 10 запросов на ремонт оборудования. Тогда:

$$ 10*(12 + 12 + 12 + 50 + 8) = 940 $$

  • _id - ObjectID V = 12 байт
  • equipemntID - ObjectID V = 12 байт
  • requester - ObjectID V = 12 байт
  • description - String V = 50 байт
  • requestDate - Date V = 8 байт


Коллекция statistic. Пусть в среднем на 1 пациента приходится 10 записей операций платежа. Тогда:

$$ 10x(8 + 12 + 8) = 280x $$

  • _id - ObjectID V = 12 байт
  • date - Date V = 8 байт
  • val - Double V = 8 байт


Коллекция procedure. Пусть в среднем в клинике доступно 20 процедур/услуг, на которые можно записаться. Тогда

$$ 20*(12 + 20 + 8) = 800 $$

  • _id - ObjectID V = 12 байт
  • name - String V = 20 байт,
  • price - Double V = 8 байт


Тогда получим следующий объем данных, для хранения x пациентов. $$ V(x) = 15000106x + 106 + 69x + 675x + 1280x + 84 + 1440 + 700 + 280x + 800 = 15002756x + 2887 $$

Если сделать грубую оценку, то получится: $$ V(x) = 15002756x $$



Избыточность модели (отношение между фактическим объемом модели и “чистым” объемом данных).

В БД дублируются данные о докторе о пациенте в историях лечений/посещений клиники, у новых пациентов список снимков может быть вообще пустым, а также некоторые пациенты могут не оставлять отзывов. Тогда получаем: $$ V(x)=7500452x + 106 + 69x + 420x + 1280x + 84 + 1440 + 940 + 280x + 800 = 7501716x + 2887 $$

Отбросим свободный член, чтобы сравнить с фактическим объемом: $$ V(x) = 7501716x $$ Отношение между фактическим и "чистым" объемом данных: $$ \frac{15002756x}{7502081} = 1.9 $$




Направление роста модели при увеличении количества объектов каждой сущности

Как и раньше, выразим через количество пациентов и получим: $$ V(x) = 15002756x + 2647 $$ Отсюда видно, что рост модели при увеличении количества объектов каждой сущности линеен и зависит от количества пациентов.




Запросы к модели, с помощью которых реализуются сценарии использования

  • регистрация нового пациента
db.patient.insert({
    _id: ObjectID(),
    prof_info: {
        email,
        password
    }
    card: {
        name,
        surname,
        birthdate,
        contact,
        bloodGroup
    },
    images: []
})
  • поиск аккаунта пациента для входа в систему
db.patient.find({
    prof_info: {
        email,
        password
    }
})
  • поиск всех предстоящих встреч
db.appointments.find({})
  • поиск предстоящих встреч определенного пациента
db.appointments.find({
    patientCard: {
        name,
        surname
    }
})
  • поиск предстоящих встреч определенного доктора
db.appointments.find({
    doctor: {
        name,
        surname
    }
})
  • подсчет прибыли
db.statistic.aggregate(
    {$group: {
            _id: "_id",
            profit: {$sum: "$val"}
    }}
)
  • просмотр оборудований клиники
db.equipment.find({})
  • просмотр оборудований, которые ремонтируются:
db.serviceRequest.aggregate({[
    {
        $lookup: {
            from: "equipment",
            localField: "equipmentID",
            foreignField: "_id",
            as: "eq_id" 
        },
        {$unwind: "$eq_id"},
        {
          $lookup: {
            from: "administrator",
            localField: "requesterID",
            foreignField: "_id",
            as: "req_id" 
        },  
        }
    }
]})

Реляционная модель

Графическое представление

image

Описание назначений коллекций, типов данных и сущностей

Разница от нереляционной версии:

  • наличие отдельной таблицы Image для хранения снимков
  • отдельная таблица History для хранения истории

Поля и типы данных полей идентичны.

Оценка объема информации, хранимой в модели

Таблица Patient. Оценим объем информации через x, где x - количество пациентов.

$$ x*(8+15+...) = 102x $$

  • _id - тип INT V = 8 байт
  • name - VARCHAR V = 15 байт
  • surname - VARCHAR V = 15 байт
  • email - VARCHAR V = 30 байт
  • password - VARCHAR V = 12 байт
  • birthdate - Date V = 8 байт
  • contact - VARCHAR V = 12 байт
  • bloodGroup - VARCHAR V = 2 байта


Таблица Image. Пусть в среднем у каждого пациента 3 снимка. Тогда выразим через количество пациентов x

$$ x3(8 + 8 + 12 + 5000000 + 8) = 15000108x$$

  • _id - тип INT V = 8 байт
  • date - Date V = 8 байт
  • name - VARCHAR V = 12 байт
  • img - Binary Data (допустим, что средний размер снимка 5 Мб) V = 5 МБайт
  • patient_id Int V = 8 байт


Таблица Statistic. Пусть в среднем на 1 пациента прходится 10 записей. Тогда

$$ 10x(8+8+20) = 360x $$

  • _id - тип INT V = 8 байт
  • date - Date V = 8 байт
  • val - VARCHAR V = 20 байт

Таблица Appointments. Пусть в среднем 10 записей на каждого пациента x. Тогда

$$ 10x(8+8+8+8+8)=450x $$

  • _id - тип INT V = 8 байт
  • date - Date V = 8 байт
  • procedure_id - Int V = 8 байт
  • patient_id - Int V = 8 байт
  • doctor_id - Int V = 8 байт


Таблица ServiceRequest. Пусть в среднем 10 запросов на ремонт оборудования. Тогда

$$ 10*(8+8+8+8) = 320 $$

  • _id - тип INT V = 8 байт
  • equipment_id - Int V = 8 байт
  • requester_id - Int V = 8 байт
  • requestDate - Date V = 8 байт


Таблица Equipment. Пусть в среднем 20 оборудований. Тогда

$$ 20*(8+50+8+10)=1520 $$

  • _id - тип INT V = 8 байт
  • name - VARCHAR V = 50 байт
  • lastService - Date V = 8 байт
  • status - VARCHAR V = 10 байт


Таблица Procedure. Пусть в среднем в клинике доступно 20 процедур/услуг. Тогда

$$ 20*(8+20+8) = 720 $$

  • _id - тип INT V = 8 байт
  • name - VARCHAR V = 20 байт
  • price - Double V = 8 байт


Таблица History. Пусть в среднем у каждого пациента 5 записей в истории. Тогда

$$ 5x(8+8+8+8+8+1+50)=480x $$

  • _id - тип INT V = 8 байт
  • date - Date V = 8 байт
  • procedure_id - Int V = 8 байт
  • patient_id - Int V = 8 байт
  • doctor_id - Int V = 8 байт
  • treat_rate - VARCHAR V = 1 байт
  • treat_feedback - VARCHAR V = 50 байт


Таблица Doctor. Пусть на каждые 10 пациентов приходится 1 доктор. Тогда

$$ (x/10 + 1)*(8+15+15+30+12+8+12+8)=108+10.5x = 11x + 108 $$

  • _id - тип INT V = 8 байт
  • name - VARCHAR V = 15 байт
  • surname - VARCHAR V = 15 байт
  • email - VARCHAR V = 30 байт
  • password - VARCHAR V = 12 байт
  • birthdate - Date V = 8 байт
  • contact - VARCHAR V = 12 байт
  • experience - Int V = 8 байт


Таблица Administrator. Пусть в среднем 1 аккаунт админа. Тогда

$$ 8 + 15 + 15 + 30 + 12 = 80 $$

  • _id - тип INT V = 8 байт
  • name - VARCHAR V = 15 байт
  • surname - VARCHAR V = 15 байт
  • email - VARCHAR V = 30 байт
  • password - VARCHAR V = 12 байт


Тогда получим следующий объем данных, для хранения x пациентов. $$ V(x) = 102x + 15000108x + 360x + 450x + 320 + 1520 + 720 + 480x + 108 +11x + 80 = 15001511x + 2748 $$


Направление роста модели при увеличении количества объектов каждой сущности

$$ V(x) = 102x + 15000108x + 360x + 450x + 320 + 1520 + 720 + 480x + 108 +11x + 80 = 15001511x + 2748 $$ Рост модели линеен.


Запросы к модели, с помощью которых реализуются сценарии использования

  • регистрация нового пациента
INSERT INTO Patient VALUES (1, "Ivan", "Ivanov", "[email protected]", "qwe123asdfzx", "12.12.2000", "+74523418754", "1+")
  • поиск аккаунта пациента для входа в систему
SELECT * FROM Patient WHERE email=email, password=password;
  • поиск всех предстоящих встреч
SELECT * FROM Appointment;
  • поиск предстоящих встреч определенного пациента
SELECT * 
FROM Patient
    INNER JOIN Appointment ON Patient.id=Appointment.patient_id
WHERE Patient.name=name AND Patient.surname=surname;
  • поиск предстоящих встреч определенного доктора
SELECT * 
FROM Doctor
    INNER JOIN Appointment ON Doctor.id=Appointment.doctor_id
WHERE Doctor.name=name AND Doctor.surname=surname;
  • подсчет прибыли
SELECT SUM(val) FROM Statistic;
  • просмотр оборудований клиники
SELECT * FROM Equipment;
  • просмотр оборудований, которые ремонтируются:
SELECT * FROM ServiceRequest 
    JOIN Equipment ON Equipment.id=equipment_id
    JOIN Administrator ON Administrator.id=requester_id
 ;

Сравнение моделей

  • NoSQL требует больше памяти, по сравнению с SQL, так в нем дублируются некоторые данные. SQL выигрывает по памяти, так как вместо того, чтобы хранить сами объекты целиком (как NoSQL), он хранит только id определенного элемента из другой таблицы.
  • По удобству запросов выигрывает NoSQL, так как ввиду дублирования данных в некоторых сущностях, нам не приходится JOIN-ить с другими коллекциями. Для некоторых запросов SQL приходится JOIN-ить несколько таблиц, что может сказать в скорости доступа.

Вывод

NoSQL требует больше памяти, но удобен и быстр в запросах, в то время как SQL требует меньше памяти и не совсем удобен в запросах, из-за того что приходится JOIN-ить таблицы. Для данной задачи NoSQL подходит лучше, чем SQL.

Примеры хранения данных в БД

Коллекция patient

image

Коллекция doctor

image

Коллекция appointment

image

Коллекция administrator

image

Коллекция equipment

image

Коллекция serviceRequest

image

Коллекция statistic

image

Коллекция procedure

image

Clone this wiki locally