-
Notifications
You must be signed in to change notification settings - Fork 0
Модель данных
n − максимально необходимый размер строки для текста. Оптимальное n = 500 символов.
Назначение: Хранит информацию о пользователях системы, их идентификацию и роли.
Атрибуты:
-
id (PK) — уникальный идентификатор пользователя, тип: INT (4 байта)
-
surname — фамилия пользователя, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
name — имя пользователя, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
lastname — отчество пользователя, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
username — уникальный логин для входа, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
password — зашифрованный пароль пользователя, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
role — роль пользователя в системе (Администратор, Прораб, Рабочий, Заказчик), тип: ENUM (1 байт (считаем 4 возможных значения))
-
created_at — Время создания записи пользователя. Это поле автоматически фиксирует дату и время, когда учетная запись пользователя была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи пользователя. Это поле автоматически обновляется при каждом изменении данных пользователя, тип TIMESTAMP (8 байт)
Общий размер: приблизительно 5n+31 байт на пользователя
Связи:
-
Один пользователь может участвовать в нескольких проектах.
-
Один пользователь может быть отправителем или получателем нескольких сообщений.
Назначение: Хранит информацию о проектах по организации ремонта, включая этапы и задачи.
Атрибуты:
-
id (PK) — уникальный идентификатор проекта, тип: INT (4 байта)
-
name — название проекта, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
description — описание проекта, тип: TEXT (до n+2 байт (n символов + служебная информация))
-
start_date — дата начала проекта, тип: DATE (3 байта)
-
end_date — дата окончания проекта, тип: DATE (3 байта)
-
status — статус проекта (в работе, завершён), тип: ENUM (1 байт (считаем 4 возможных значения))
-
contact_id (FK) — идентификатор контактов (ссылка на контакты), тип: INT (4 байта)
-
created_at — Время создания записи проекта. Это поле автоматически фиксирует дату и время, когда учетная запись проекта была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи проекта. Это поле автоматически обновляется при каждом изменении данных проекта, тип TIMESTAMP (8 байт)
Общий размер: приблизительно 2n+41 байт на пользователя
Связи:
-
Один проект может включать несколько этапов.
-
Проект содержит этапы, риски и закупки.
Назначение: Хранит информацию об этапах проекта.
Атрибуты:
-
id (PK) — уникальный идентификатор этапа, тип: INT (4 байта)
-
name — название этапа, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
start_date — дата начала этапа, тип: DATE (3 байта)
-
end_date — дата окончания этапа, тип: DATE (3 байта)
-
project_id (FK) — идентификатор проекта, к которому относится этап, тип: INT (4 байта)
-
created_at — Время создания записи этапа. Это поле автоматически фиксирует дату и время, когда учетная запись этапа была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи этапа. Это поле автоматически обновляется при каждом изменении данных этапа, тип TIMESTAMP (8 байт)
-
Общий размер: приблизительно n+32 байт на этап.
Связи:
-
Этап включает несколько задач.
-
Этап связан с одним проектом.
Назначение: Хранит информацию о задачах, связанных с этапами проекта.
Атрибуты:
-
id (PK) — уникальный идентификатор задачи, тип: INT (4 байта)
-
name — название задачи, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
description — описание задачи, тип: TEXT (до n+2 байт (n символов + служебная информация))
-
start_date — дата начала задачи, тип: DATE (3 байта)
-
end_date — дата окончания задачи, тип: DATE (3 байта)
-
status — статус задачи (запланировано, в работе, завершено), тип: ENUM (1 байт)
-
stage_id (FK) — идентификатор этапа, к которому относится задача, тип: INT (4 байта)
-
contact_id (FK) — идентификатор рабочего, ответственного за задачу, тип: INT (4 байта)
-
created_at — Время создания записи задачи. Это поле автоматически фиксирует дату и время, когда учетная запись задачи была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи задачи. Это поле автоматически обновляется при каждом изменении данных задачи, тип TIMESTAMP (8 байт)
Общий размер: приблизительно 2n+39 байт на задачу.
Связи:
-
Задача может быть связана с несколькими рабочими через связь многие ко многим.
-
Задача может быть связана с этапом через связь один ко многим.
Назначение: Хранит информацию о сообщениях между пользователями.
Атрибуты:
-
id (PK) — уникальный идентификатор сообщения, тип: INT (4 байта)
-
text — текст сообщения, тип: TEXT (до n+2 байт (n символов + служебная информация))
-
sent_date — дата отправки сообщения, тип: DATETIME (8 байт)
-
sender_id (FK) — идентификатор отправителя (ссылка на пользователя), тип: INT (4 байта)
-
receiver_id (FK) — идентификатор получателя (ссылка на пользователя), тип: INT (4 байта)
-
status — статус сообщения (прочитано или нет), тип: ENUM (1 байт)
-
created_at — Время создания записи сообщения. Это поле автоматически фиксирует дату и время, когда учетная запись сообщения была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи сообщения. Это поле автоматически обновляется при каждом изменении данных сообщения, тип TIMESTAMP (8 байт)
Общий размер: приблизительно n+39 байт на сообщение.
Связи:
-Одно сообщение может быть отправлено одним пользователем и направлено другому пользователю.
Назначение: Хранит информацию о закупках материалов для проектов.
Атрибуты:
-
id (PK) — уникальный идентификатор закупки, тип: INT (4 байта)
-
item_name — наименование закупаемого товара, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
quantity — количество товара, тип: INT (4 байта)
-
price — цена товара, тип: DECIMAL (8 байт)
-
created_date — дата создания закупки, тип: TIMESTAMP (8 байт)
-
project_id (FK) — идентификатор проекта, связанного с закупкой, тип: INT (4 байта)
-
created_at — Время создания записи закупки. Это поле автоматически фиксирует дату и время, когда учетная запись закупки была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи закупки. Это поле автоматически обновляется при каждом изменении данных закупки, тип TIMESTAMP (8 байт)
-
created_by (FK) — идентификатор пользователя, который создал закупку, тип: INT (4 байта)
-
delivery_date — дата поставки, тип: DATE (3 байта)
Общий размер: приблизительно n+46 байт на сообщение.
Связи:
- Одна закупка привязана к одному проекту.
Назначение: Хранит информацию о рисках, связанных с проектами.
Атрибуты:
-
id (PK) — уникальный идентификатор риска, тип: INT (4 байта)
-
name — название риска, тип: VARCHAR (до n+2 байт (n символов + служебная информация))
-
description — описание риска, тип: TEXT (до n+2 байт (n символов + служебная информация))
-
project_id (FK) — идентификатор проекта, к которому относится риск, тип: INT (4 байта)
-
created_at — Время создания записи риски. Это поле автоматически фиксирует дату и время, когда учетная запись риска была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи риска. Это поле автоматически обновляется при каждом изменении данных риска, тип TIMESTAMP (8 байта)
Общий размер: приблизительно 2n+ 28 байт на риск
Связи:
- Один проект может иметь несколько рисков.
Назначение: Хранит информацию о пользователях и проектах, в которых они участвуют.
Атрибуты:
-
id (PK) — уникальный идентификатор контакта, тип: INT (4 байта)
-
user_id (FK) — идентификатор пользователя, тип: INT (4 байта)
-
project_id (FK) — идентификатор проекта, тип: INT (4 байта)
-
created_at — Время создания записи контакта. Это поле автоматически фиксирует дату и время, когда учетная запись контакта была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи контакта. Это поле автоматически обновляется при каждом изменении данных контакта, тип TIMESTAMP (8 байт)
Общий размер: приблизительно 28 байт на контакт
Связи:
- Один контакт связывает пользователя с проектом.
Назначение: Хранит информацию о пользователях и проектах, в которых они участвуют.
Атрибуты:
-
id (PK) — уникальный идентификатор контакта, тип: INT (4 байта)
-
user_id (FK) — идентификатор пользователя, тип: INT (4 байта)
-
task_id (FK) — идентификатор задачи, тип: INT (4 байта)
-
created_at — Время создания записи таблицы. Это поле автоматически фиксирует дату и время, когда учетная запись в таблицу была создана в системе, тип TIMESTAMP (8 байт)
-
updated_at — Время последнего обновления записи в таблицу. Это поле автоматически обновляется при каждом изменении данных таблицы, тип TIMESTAMP (8 байт)
Общий размер: приблизительно 28 байт на таблицу Работник_Задача
Связи:
- Много задач связаны с многими работниками.
Средний размер одного документа коллекции:
-
User: 5n+3 + 24 (оверхед строки) = 2527 байт
-
Project: 2n+41 +24 (оверхед строки) = 1065 байт
-
Stage: n+32 = 532 байт
-
Task: 2n+39 + 24 (оверхед строки) = 1063 байт
-
Message: n+39+ 24 (оверхед строки) = 563 байт
-
Procurement: n+46 = 546 байт
-
Risk: 2n+ 28 + 24 (оверхед строки) = 1052 байт
-
Contact: 28 байт
Предположительно пользователь будет создавать:
-
заказчиков в среднем u
-
в среднем прорабов u
-
в среднем работников 8*u
-
в среднем 1*u проектов
-
в среднем 3 этапа на проект
-
в среднем 5 задач на этап
-
в среднем 105u рассылок + 630u сообщений между пользователями
-
в среднем 100 закупок на проект
-
в среднем 8 рабочих + 1 прораб+ 1 заказчик на проект
-
в среднем 5 рисков на проект
При количестве заказчиков равным u:
V(u)=(252710 +735563+1065+3532+106315+100546+51052+10*28) ∗u= 516221∗u
-
В таблице User: избыточные данные id, created_at, updated_at (20 байт)
-
В таблице Project: избыточные данные id, created_at, updated_at, project_id (24 байт)
-
В таблице Stage: избыточные данные id, created_at, updated_at, project_id (24 байт)
-
В таблице Task: избыточные данные id, created_at, updated_at, stage_id, worker_id (28 байт)
-
В таблице Message: избыточные данные id, created_at, updated_at, receiver_id, sender_id (28 байт)
-
В таблице Procurement: избыточные данные id, created_at, updated_at, project_id (24 байт)
-
В таблице Risk: избыточные данные id, created_at, updated_at, project_id (24 байт)
-
В таблице Contact: избыточные данные вся таблица.
При количестве заказчиков равным u:
Vclean(u)=(250710 +1041+3508+103515+735535+100522+51028) ∗u=493625∗u
Тогда рассчитаем избыточность как отношение объема модели к "чистому" объему:
V(u)/Vclean(u)=516221∗u/493625∗u≈1,0457
При создании модели Project будут создаваться модели Stage, Task, Procurement, Risk, Contact
При добавлении других моделей (User, Message) ничего создаваться дополнительно не будет
id | surname | name | lastname | username | password | role | created_at | updated_at |
---|---|---|---|---|---|---|---|---|
1 | Иванов | Иван | Иванович | ivanov_ivan | e5d3be45bfeabc | Администратор | 2024-10-10 09:00:00 | 2024-10-10 09:00:00 |
2 | Смирнова | Анна | Сергеевна | smirnova_anna | 9aaf7cc6dce123 | Заказчик | 2024-10-12 10:20:00 | 2024-10-12 10:20:00 |
3 | Петров | Петр | Петрович | petrov_petr | c23b5d7f4fa2d7 | Прораб | 2024-10-13 11:30:00 | 2024-10-13 11:30:00 |
4 | Сидоров | Сергей | Викторович | sidorov_sergey | f12e9873df129a | Рабочий | 2024-10-14 12:15:00 | 2024-10-14 12:15:00 |
id | name | description | start_date | end_date | status | customer_id | foreman_id | created_at | updated_at |
---|---|---|---|---|---|---|---|---|---|
1 | Ремонт офиса | Проект по ремонту офисного здания | 2024-11-01 | 2024-12-20 | в работе | 2 | 3 | 2024-10-12 10:25:00 | 2024-10-12 10:25:00 |
2 | Строительство склада | Строительство складского помещения | 2024-11-15 | 2025-01-30 | в работе | 2 | 3 | 2024-10-13 11:35:00 | 2024-10-13 11:35:00 |
id | name | description | start_date | end_date | status | stage_id | worker_id | created_at | updated_at |
---|---|---|---|---|---|---|---|---|---|
1 | Установка розеток | Монтаж электророзеток в офисе | 2024-11-16 | 2024-11-17 | запланировано | 2 | 4 | 2024-10-14 12:20:00 | 2024-10-14 12:20:00 |
2 | Укладка плитки | Укладка плитки в санузлах офиса | 2024-11-18 | 2024-11-20 | запланировано | 2 | 4 | 2024-10-14 12:25:00 | 2024-10-14 12:25:00 |
id | name | start_date | end_date | project_id | created_at | updated_at |
---|---|---|---|---|---|---|
1 | Дизайн интерьера | 2024-11-01 | 2024-11-15 | 1 | 2024-10-12 10:30:00 | 2024-10-12 10:30:00 |
2 | Электромонтажные работы | 2024-11-16 | 2024-11-30 | 1 | 2024-10-13 11:40:00 | 2024-10-13 11:40:00 |
id | text | sent_date | sender_id | receiver_id | status | created_at | updated_at |
---|---|---|---|---|---|---|---|
1 | Здравствуйте, когда начнется проект? | 2024-10-12 10:30:00 | 2 | 3 | прочитано | 2024-10-12 10:30:00 | 2024-10-12 10:30:00 |
2 | Утверждаю смету | 2024-10-13 11:35:00 | 2 | 3 | не прочитано | 2024 |
id | item_name | quantity | price | created_date | project_id | created_at | updated_at |
---|---|---|---|---|---|---|---|
1 | Электрические кабели | 1000 | 50000 | 2024-10-15 14:00:00 | 1 | 2024-10-15 14:00:00 | 2024-10-15 14:00:00 |
2 | Плитка керамическая | 500 | 30000 | 2024-10-16 10:15:00 | 1 | 2024-10-16 10:15:00 | 2024-10-16 10:15:00 |
id | user_id | project_id | created_at | updated_at |
---|---|---|---|---|
1 | 2 | 1 | 2024-10-12 10:50:00 | 2024-10-12 10:50:00 |
2 | 3 | 1 | 2024-10-12 10:51:00 | 2024-10-12 10:51:00 |
id | item_name | quantity | price | created_date | project_id | created_at | updated_at |
---|---|---|---|---|---|---|---|
1 | Электрические кабели | 1000 | 50000 | 2024-10-15 14:00:00 | 1 | 2024-10-15 14:00:00 | 2024-10-15 14:00:00 |
2 | Плитка керамическая | 500 | 30000 | 2024-10-16 10:15:00 | 1 | 2024-10-16 10:15:00 | 2024-10-16 10:15:00 |
id | name | description | project_id | created_at | updated_at |
---|---|---|---|---|---|
1 | Задержка поставки материалов | Возможная задержка поставок | 1 | 2024-10-12 10:40:00 | 2024-10-12 10:40:00 |
2 | Отсутствие рабочей силы | Нехватка работников для укладки плитки | 1 | 2024-10-13 11:45:00 | 2024-10-13 11:45:00 |
Запрос на регистрацию пользователя:
INSERT INTO users (username, password_hash, email, role_id)
VALUES (:username, :password_hash, :email, :role_id);
Запрос на получение роли пользователя:
SELECT role_id FROM roles WHERE role_name = :role_name;
Запрос на создание логина и пароля:
UPDATE users SET password_hash = :password_hash WHERE email = :email;
Запрос на поиск пользователя по фамилии, имени или должности:
SELECT * FROM users WHERE last_name = :last_name OR first_name = :first_name OR position = :position;
Запрос на отправку сообщения:
INSERT INTO messages (chat_id, sender_id, content, timestamp)
VALUES (:chat_id, :sender_id, :content, NOW());
Запрос получение сообщений от пользователя:
INSERT INTO messages (chat_id, sender_id, content, timestamp)
VALUES (:chat_id, :sender_id, :content, NOW());
Запрос на получение задач рабочего:
SELECT * FROM tasks WHERE assigned_worker_id = :worker_id
AND (status = 'active' OR status = 'in_progress');
Запрос на фильтрацию задач:
SELECT * FROM tasks WHERE project_id = :project_id AND status = :status AND task_date BETWEEN :start_date AND :end_date;
Запрос на создание проекта:
INSERT INTO projects (name, description, client_id, start_date, end_date, status)
VALUES (:name, :description, :client_id, :start_date, :end_date, 'pending');
Запрос на назначение прораба на проект:
UPDATE projects SET foreman_id = :foreman_id WHERE project_id = :project_id;
Запрос на просмотр информации о проекте:
SELECT * FROM projects WHERE project_id = :project_id;
Запрос на редактирование проекта:
UPDATE projects SET description = :description, start_date = :start_date, end_date = :end_date WHERE project_id = :project_id;
Запрос на добавление материалов в закупки:
INSERT INTO purchases (project_id, item_name, quantity, unit_price)
VALUES (:project_id, :item_name, :quantity, :unit_price);
Запрос на редактирование закупки:
UPDATE purchases SET item_name = :item_name, quantity = :quantity, unit_price = :unit_price WHERE purchase_id = :purchase_id;
Запрос на добавление рисков проекта:
INSERT INTO risks (project_id, risk_name, description)
VALUES (:project_id, :risk_name, :description);
Запрос на редактирование риска:
UPDATE risks SET risk_name = :risk_name, description = :description WHERE risk_id = :risk_id;
Запрос на добавление контакта в проект:
INSERT INTO project_contacts (project_id, user_id)
VALUES (:project_id, :user_id);
Запрос на удаление контакта:
DELETE FROM project_contacts WHERE project_id = :project_id AND user_id = :user_id;
Запрос на добавление этапа проекта:
INSERT INTO stages (project_id, stage_name, start_date, end_date)
VALUES (:project_id, :stage_name, :start_date, :end_date);
Запрос на редактирование этапа:
UPDATE stages SET stage_name = :stage_name, start_date = :start_date, end_date = :end_date WHERE stage_id = :stage_id;
Запрос на создание задачи:
INSERT INTO tasks (stage_id, task_name, start_date, end_date, worker_id, status)
VALUES (:stage_id, :task_name, :start_date, :end_date, :worker_id, 'pending');
Запрос на редактирование задачи:
UPDATE tasks SET task_name = :task_name, start_date = :start_date, end_date = :end_date, status = :status WHERE task_id = :task_id;
Запрос на экспорт данных проекта для анализа:
COPY projects TO '/path/projects.csv' WITH (FORMAT csv, HEADER);
Запрос на импорт данных в проект:
COPY projects FROM '/path/projects.csv' WITH (FORMAT csv, HEADER);
Получение статистики по рискам
SELECT *
FROM risks
WHERE project_id IN ('60f1b8d4e138234068a9099a', '60f1b8d4e138234068a9099b')
AND created_date BETWEEN '2023-01-01' AND '2023-12-31';
Получение статистики по закупкам
SELECT *
FROM procurements
WHERE project_id IN ('60f1b8d4e138234068a9099a', '60f1b8d4e138234068a9099b')
AND created_date BETWEEN '2023-01-01' AND '2023-12-31';
SELECT
m.id,
m.text,
m.sent_date,
m.sender_id,
m.receiver_id,
m.status,
m.created_at,
m.updated_at
FROM
messages m
WHERE
m.status = 'непрочитано';
SELECT
s.id AS stage_id,
s.name AS stage_name,
SUM(p.price * p.quantity) AS total_procurement_amount
FROM
procurements p
JOIN
projects pr ON pr.id = p.project_id
JOIN
stages s ON s.project_id = pr.id
GROUP BY
s.id, s.name
ORDER BY
s.id;
Картинка
{
"_id": "ObjectID", // Уникальный идентификатор
"surname": "String", // Фамилия пользователя
"name": "String", // Имя пользователя
"father_name": "String", // Отчество пользователя
"username": "String", // Логин пользователя
"password": "String", // Хеш пароля
"role": "String", // Роль пользователя (можно также использовать ENUM-подобную логику с набором ролей)
"created_at": "ISODate", // Дата создания
"updated_at": "ISODate", // Дата последнего обновления
}
{
"_id": "ObjectId", // Уникальный идентификатор проекта
"name": "String", // Название проекта
"description": "String", // Описание проекта
"start_date": "ISODate", // Дата начала проекта
"end_date": "ISODate", // Дата окончания проекта
"status": "String", // Статус проекта (в работе/завершён)
"created_at": "ISODate", // Дата создания
"updated_at": "ISODate", // Дата последнего обновления
"contacts": { // Контакты, связанные с проектом
"contact_id_1": {
"user_id": "ObjectId", // Идентификатор пользователя
"created_at": "ISODate", // Дата создания контакта
"updated_at": "ISODate" // Дата обновления контакта
},
"contact_id_2": {
"user_id": "ObjectId",
"created_at": "ISODate",
"updated_at": "ISODate"
}
},
"stages": { // Этапы проекта
"stage_id_1": {
"name": "String", // Название этапа
"start_date": "ISODate", // Дата начала этапа
"end_date": "ISODate", // Дата окончания этапа
"created_date": "ISODate", // Дата создания этапа
"updated_at": "ISODate", // Дата обновления этапа
"tasks": { // Задачи этапа
"task_id_1": {
"name": "String", // Название задачи
"description": "String", // Описание задачи
"start_date": "ISODate", // Дата начала задачи
"end_date": "ISODate", // Дата окончания задачи
"status": "String", // Статус задачи
"created_at": "ISODate",
"updated_at": "ISODate",
"workers": {
"worker_id_1": { // Рабочий, назначенный на задачу
"user_id": "ObjectId", // Идентификатор пользователя
"name": "String" // Имя рабочего
}
}
}
}
}
},
"risks": { // Риски, связанные с проектом
"risk_id_1": {
"name": "String", // Название риска
"description": "String", // Описание риска
"created_at": "ISODate", // Дата создания риска
"updated_at": "ISODate" // Дата обновления риска
},
"risk_id_2": {
"name": "String",
"description": "String",
"created_at": "ISODate",
"updated_at": "ISODate"
}
},
"procurements": { // Закупки, связанные с проектом
"procurement_id_1": {
"item_name": "String", // Наименование товара
"quantity": "Number", // Количество товара
"price": "Number", // Цена товара
"created_by": "ObjectId", // Идентификатор пользователя, создавшего закупку
"created_date": "ISODate", // Дата создания закупки
"updated_at": "ISODate", // Дата обновления закупки
"delivery_date": "ISODate" // Дата поставки товара
},
"procurement_id_2": {
"item_name": "String",
"quantity": "Number",
"price": "Number",
"created_by": "ObjectId",
"created_date": "ISODate",
"updated_at": "ISODate",
"delivery_date": "ISODate"
}
}
}
{
"_id": "ObjectId", // Уникальный идентификатор сообщения
"chatId": "ObjectId", // Идентификатор чата, к которому относится сообщение
"sender": "ObjectId", // Идентификатор отправителя
"receiver": "ObjectId", // Идентификатор получателя
"content": "string", // Содержание сообщения
"status": "string", // Статус сообщения (например, "unread", "read")
"timestamp": "ISODate" // Временная метка сообщения
}
{
"_id": "ObjectId", // Уникальный идентификатор этапа
"name": "String", // Название этапа
"start_date": "ISODate", // Дата начала этапа
"end_date": "ISODate", // Дата окончания этапа
"created_date": "ISODate", // Дата создания этапа
"updated_at": "ISODate", // Дата последнего обновления
"tasks": { // Список задач этапа
"task_id_1": {
"name": "String", // Название задачи
"description": "String", // Описание задачи
"start_date": "ISODate", // Дата начала задачи
"end_date": "ISODate", // Дата окончания задачи
"status": "String", // Статус задачи (запланировано/в работе/завершено)
"created_at": "ISODate", // Дата создания задачи
"updated_at": "ISODate", // Дата обновления задачи
"workers": { // Список рабочих, ответственных за задачу
"worker_id_1": {
"user_id": "ObjectId", // Идентификатор рабочего
"name": "String" // Имя рабочего
}
}
}
}
}
{
"_id": "ObjectId", // Уникальный идентификатор закупки
"item_name": "String", // Наименование товара
"quantity": "Number", // Количество товара
"price": "Number", // Цена товара
"created_by": "ObjectId", // Идентификатор пользователя, создавшего закупку
"created_date": "ISODate", // Дата создания закупки
"updated_at": "ISODate", // Дата последнего обновления
"delivery_date": "ISODate", // Дата поставки товара
"project_id": "ObjectId" // Идентификатор связанного проекта
}
{
"_id": "ObjectId", // Уникальный идентификатор риска
"name": "String", // Название риска
"description": "String", // Описание риска
"created_at": "ISODate", // Дата создания
"updated_at": "ISODate" // Дата обновления
}
{
"_id": "ObjectId", // Уникальный идентификатор контакта
"user_id": "ObjectId", // Идентификатор пользователя
"project_id": "ObjectId", // Идентификатор проекта
"created_at": "ISODate", // Дата создания контакта
"updated_at": "ISODate" // Дата обновления
}
{
"tasks": { // Словарь задач в рамках этапа
"task_id_1": { // Идентификатор задачи
"name": "String", // Название задачи
"description": "String", // Описание задачи
"start_date": "ISODate", // Дата начала задачи
"end_date": "ISODate", // Дата окончания задачи
"status": "String", // Статус задачи (запланировано/в работе/завершено)
"created_at": "ISODate", // Дата создания задачи
"updated_at": "ISODate", // Дата обновления задачи
"workers": { // Список рабочих, ответственных за задачу
"worker_id_1": { // Идентификатор рабочего
"user_id": "ObjectId", // Идентификатор пользователя
"name": "String" // Имя рабочего
},
"worker_id_2": {
"user_id": "ObjectId",
"name": "String"
}
}
},
"task_id_2": {
"name": "String",
"description": "String",
"start_date": "ISODate",
"end_date": "ISODate",
"status": "String",
"created_at": "ISODate",
"updated_at": "ISODate",
"workers": {
"worker_id_1": {
"user_id": "ObjectId",
"name": "String"
}
}
}
}
}
{
"_id": "ObjectId", // Уникальный идентификатор чата
"participants": { // Словарь участников чата
"user1_id": { // Идентификатор пользователя
"name": "string", // Имя пользователя
"lastSeen": "ISODate" // Временная метка последнего просмотра
},
"user2_id": { // Идентификатор пользователя
"name": "string", // Имя пользователя
"lastSeen": "ISODate" // Временная метка последнего просмотра
}
},
"lastMessage": { // Последнее сообщение в чате
"content": "string", // Содержание сообщения
"sender": "string", // Идентификатор отправителя
"status": "string", // Статус сообщения (например, "unread", "read")
"timestamp": "ISODate" // Временная метка сообщения
},
"createdAt": "ISODate", // Временная метка создания чата
"updatedAt": "ISODate" // Временная метка последнего обновления чата
}
Предположительно пользователь будет создавать:
-
заказчиков в среднем u
-
в среднем прорабов u
-
в среднем работников 8*u
-
в среднем 1*u проектов
-
в среднем 3 этапа на проект
-
в среднем 5 задач на этап
-
в среднем 105u рассылок + 630u сообщений между пользователями
-
в среднем 100 закупок на проект
-
в среднем 8 рабочих + 1 прораб+ 1 заказчик на проект
-
в среднем 5 рисков на проект
{
"_id": "ObjectId": 12 байт,
"surname": "String": 500 байт,
"name": "String": 500 байт,
"father_name": "String": 500 байт,
"username": "String": 500 байт,
"password": "String": 500 байт,
"role": "String": 50 байт,
"created_at": "ISODate": 8 байт,
"updated_at": "ISODate": 8 байт
}
- Общий размер: приблизительно 2578 байт.
{
"_id": {
"type": "ObjectId",
"size_bytes": 12
},
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"status": {
"type": "String",
"size_bytes": 50
},
"created_at": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
},
"contacts": {
"contact_id_1": {
"user_id": {
"type": "ObjectId",
"size_bytes": 12
},
"created_at": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
}
},
"contact_id_2": {
"user_id": {
"type": "ObjectId",
"size_bytes": 12
},
"created_at": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
}
},
"total_size_bytes": 56
},
"stages": {
"stage_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"created_date": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
},
"tasks": {
"task_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"status": {
"type": "String",
"size_bytes": 50
},
"created_at": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
},
"workers": {
"worker_id_1": {
"user_id": {
"type": "ObjectId",
"size_bytes": 12
},
"name": {
"type": "String",
"size_bytes": 50
}
},
"total_size_bytes": 62
},
"total_size_bytes": 1644
},
"total_size_bytes": 1644
},
"total_size_bytes": 536
},
"total_size_bytes": 536
},
"risks": {
"risk_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
"created_at": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
}
},
"total_size_bytes": 1516
},
"procurements": {
"procurement_id_1": {
"item_name": {
"type": "String",
"size_bytes": 500
},
"quantity": {
"type": "Number",
"size_bytes": 8
},
"price": {
"type": "Number",
"size_bytes": 8
},
"created_by": {
"type": "ObjectId",
"size_bytes": 12
},
"created_date": {
"type": "ISODate",
"size_bytes": 8
},
"updated_at": {
"type": "ISODate",
"size_bytes": 8
},
"delivery_date": {
"type": "ISODate",
"size_bytes": 8
}
},
"total_size_bytes": 540
},
"total_document_size_bytes":
}
- Общий размер: приблизительно 12114 байт
{
"_id": "ObjectId": 12 байт,
"name": "String": 500 байт,
"description": "String": 1000 байт,
"start_date": "ISODate": 8 байт,
"end_date": "ISODate": 8 байт,
"status": "String": 50 байт,
"created_at": "ISODate": 8 байт,
"updated_at": "ISODate": 8 байт,
"workers": [{ // Предположим 3 работника
"user_id": "ObjectId": 12 байт,
"name": "String": 500 байт
}] * 3 = (12 * 3 + 500 * 3) = 1536 байт
}
- Общий размер: приблизительно 3130 байт
{
"_id": "ObjectId": 12 байт,
"item_name": "String": 500 байт,
"quantity": "Number": 8 байт,
"price": "Number": 8 байт,
"created_date": "ISODate": 8 байт,
"updated_at": "ISODate": 8 байт,
"project_id": "ObjectId": 12 байт
}
- Общий размер: приблизительно 556 байт
{
"_id": "12 байт",
"participants": {
"user1_id": {
"name": "50 байт",
"lastSeen": "8 байт"
},
"user2_id": {
"name": "50 байт",
"lastSeen": "8 байт"
}
},
"lastMessage": {
"content": "200 байт",
"sender": "50 байт",
"status": "20 байт",
"timestamp": "8 байт"
},
"createdAt": "8 байт",
"updatedAt": "8 байт",
}
- Общий размер: приблизительно 422 байт
V(u)=(2578×10 + 422×8+ 12114+735×570+15×3130+556×100)×u= 562770×u
-
заказчиков в среднем u
-
в среднем прорабов u
-
в среднем работников 8*u
-
в среднем 1*u проектов
-
в среднем 3 этапа на проект
-
в среднем 5 задач на этап
-
в среднем 105×u рассылок + 630×u сообщений между пользователями
-
в среднем 100 закупок на проект
-
в среднем 8 рабочих + 1 прораб+ 1 заказчик на проект
-
в среднем 5 рисков на проект
{
"surname": "String": 500 байт,
"name": "String": 500 байт,
"father_name": "String": 500 байт,
"username": "String": 500 байт,
"password": "String": 500 байт,
"role": "String": 50 байт,
}
- Общий размер: приблизительно 2550 байт.
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"status": {
"type": "String",
"size_bytes": 50
},
"stages": {
"stage_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"tasks": {
"task_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
"start_date": {
"type": "ISODate",
"size_bytes": 8
},
"end_date": {
"type": "ISODate",
"size_bytes": 8
},
"status": {
"type": "String",
"size_bytes": 50
},
"workers": {
"worker_id_1": {
"name": {
"type": "String",
"size_bytes": 50
}
},
"total_size_bytes": 50
},
"total_size_bytes": 1564
},
},
"total_size_bytes": 516
},
},
"risks": {
"risk_id_1": {
"name": {
"type": "String",
"size_bytes": 500
},
"description": {
"type": "String",
"size_bytes": 1000
},
},
"total_size_bytes": 1500
},
"procurements": {
"procurement_id_1": {
"item_name": {
"type": "String",
"size_bytes": 500
},
"quantity": {
"type": "Number",
"size_bytes": 8
},
"price": {
"type": "Number",
"size_bytes": 8
},
"created_by": {
"type": "ObjectId",
"size_bytes": 12
},
"created_date": {
"type": "ISODate",
"size_bytes": 8
},
},
"total_size_bytes": 536
},
"total_document_size_bytes":
- Общий размер: приблизительно 10344 байт
{
"text": "String": 500 байт,
"sent_date": "ISODate": 8 байт,
"sender_id": "ObjectId": 12 байт,
"receiver_id": "ObjectId": 12 байт,
"status": "String": 10 байт
}
- Общий размер: приблизительно 542 байт
{
"name": "String": 500 байт,
"description": "String": 1000 байт,
"start_date": "ISODate": 8 байт,
"end_date": "ISODate": 8 байт,
"status": "String": 50 байт,
"workers": [{ // Предположим 3 работника
"name": "String": 500 байт
}] * 3 = (500 * 3) = 1500 байт
}
- Общий размер: приблизительно 3066 байт
{
"item_name": "String": 500 байт,
"quantity": "Number": 8 байт,
"price": "Number": 8 байт,
}
- Общий размер: приблизительно 516 байт
{
"participants": {
"user1_id": {
"name": "50 байт",
"lastSeen": "8 байт"
},
"user2_id": {
"name": "50 байт",
"lastSeen": "8 байт"
}
},
"lastMessage": {
"content": "200 байт",
"sender": "50 байт",
"status": "20 байт",
"timestamp": "8 байт"
},
}
- Общий размер: приблизительно 394 байт
Vclean(u)=(2550×10 + 394×8 + 10344+735×542+15×3066+516×100)×u =534956×u
Тогда рассчитаем избыточность как отношение объема модели к "чистому" объему:
V(u)/Vclean(u)=562770∗u/534956 ∗u≈1,052
Модель представленных данных демонстрирует несколько направлений роста, каждое из которых может влиять на общую архитектуру и производительность системы. Вот ключевые направления:
- С увеличением числа пользователей растет объем данных, что требует эффективного управления идентификаторами, паролями и ролями.
- Каждое новое добавление пользователя увеличивает объем дублированных данных, например, при хранении информации о проектах и сообщениях, связанных с пользователями.
- Каждому пользователю может быть присвоено несколько проектов, что приводит к увеличению общего объема данных.
- Увеличение количества проектов в системе требует обработки связанной информации, такой как этапы, риски и закупки, что добавляет дополнительные слои сложности.
- С увеличением числа проектов и этапов возникает необходимость в более сложной структуре для управления задачами.
- Увеличение числа задач может привести к необходимости более детальной оценки статусов и сроков выполнения, что также увеличивает объем данных.
- По мере роста количества пользователей и проектов возрастает и объем сообщений между ними. Это может привести к увеличению нагрузки на систему и потребовать оптимизации хранения и обработки данных.
- С увеличением числа проектов и их сложностью увеличивается необходимость в управлении рисками и закупками. Это требует создания более детализированных записей и статусов для рисков и закупок, что увеличивает общий объем данных.
- Увеличение числа связей между пользователями, проектами, этапами, задачами, рисками и закупками требует эффективного управления этими связями.
- С увеличением связей увеличивается сложность запросов и операций в базе данных, что может повлиять на производительность.
- Каждое новое добавление пользователя, проекта или задачи может привести к экспоненциальному увеличению избыточности данных, особенно если данные дублируются в разных коллекциях.
- Это создает необходимость в реализации методов нормализации данных и стратегий управления дублирующимися записями, чтобы минимизировать избыточность.
{
"_id": ObjectId("60c72b2f9c3d4d1234567890"),
"surname": "Иванов",
"name": "Иван",
"father_name": "Иванович",
"username": "ivanov_i",
"password": "$2a$10$CwF5W.x5Bz4L.D1BZj/R7e.OW2iWO5NOhp7M7N5QAn3ceWDhSEzy6", // Пример хеша пароля
"role": "Администратор",
"created_at": ISODate("2023-01-01T00:00:00Z"),
"updated_at": ISODate("2023-01-15T00:00:00Z")
}
{
"_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b8"),
"name": "Проект разработки ПО",
"description": "Разработка нового программного обеспечения для клиента",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-12-31T00:00:00Z"),
"status": "в работе",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"contacts": {
"contact_id_1": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b9"),
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z")
},
"contact_id_2": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7ba"),
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z")
}
},
"stages": {
"stage_id_1": {
"name": "Этап разработки",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-10-31T00:00:00Z"),
"created_date": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"tasks": {
"task_id_1": {
"name": "Разработка нового модуля",
"description": "Разработка и тестирование нового модуля для приложения",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-10-15T00:00:00Z"),
"status": "в работе",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"workers": {
"worker_id_1": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b9"),
"name": "Иван Иванов"
}
}
}
}
}
},
"risks": {
"risk_id_1": {
"name": "Риск задержки поставки",
"description": "Возможная задержка поставки оборудования",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z")
},
"risk_id_2": {
"name": "Риск нехватки ресурсов",
"description": "Возможная нехватка человеческих ресурсов",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z")
}
},
"procurements": {
"procurement_id_1": {
"item_name": "Ноутбук",
"quantity": 10,
"price": 50000,
"created_by": ObjectId("64e3b8c1f2b3c9d4e5f6a7b9"),
"created_date": ISODate("2023-10-01T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"delivery_date": ISODate("2023-10-15T00:00:00Z")
},
"procurement_id_2": {
"item_name": "Монитор",
"quantity": 5,
"price": 20000,
"created_by": ObjectId("64e3b8c1f2b3c9d4e5f6a7ba"),
"created_date": ISODate("2023-10-01T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"delivery_date": ISODate("2023-10-20T00:00:00Z")
}
}
}
{
"_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b8"),
"name": "Этап разработки",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-10-31T00:00:00Z"),
"created_date": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"tasks": {
"task_id_1": {
"name": "Разработка нового модуля",
"description": "Разработка и тестирование нового модуля для приложения",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-10-15T00:00:00Z"),
"status": "в работе",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"workers": {
"worker_id_1": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b9"),
"name": "Иван Иванов"
},
"worker_id_2": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7ba"),
"name": "Петр Петров"
}
}
},
"task_id_2": {
"name": "Обновление документации",
"description": "Обновление и дополнение документации для проекта",
"start_date": ISODate("2023-10-10T00:00:00Z"),
"end_date": ISODate("2023-10-20T00:00:00Z"),
"status": "запланировано",
"created_at": ISODate("2023-10-01T00:00:00Z"),
"updated_at": ISODate("2023-10-01T00:00:00Z"),
"workers": {
"worker_id_1": {
"user_id": ObjectId("64e3b8c1f2b3c9d4e5f6a7b9"),
"name": "Иван Иванов"
}
}
}
}
}
{
"tasks": [
{
"_id": ObjectId("60c72b2f9c3d4d1234567890"),
"name": "Разработка модуля аутентификации",
"description": "Создание и тестирование модуля аутентификации для веб-приложения.",
"start_date": ISODate("2023-10-01T00:00:00Z"),
"end_date": ISODate("2023-10-15T00:00:00Z"),
"status": "в работе",
"created_at": ISODate("2023-09-25T00:00:00Z"),
"updated_at": ISODate("2023-10-05T00:00:00Z"),
"workers": [
{
"user_id": ObjectId("60c72b2f9c3d4d1234567891"),
"name": "Иван Иванов"
},
{
"user_id": ObjectId("60c72b2f9c3d4d1234567892"),
"name": "Петр Петров"
}
]
},
{
"_id": ObjectId("60c72b2f9c3d4d1234567893"),
"name": "Тестирование интерфейса",
"description": "Проведение тестирования пользовательского интерфейса на различных устройствах.",
"start_date": ISODate("2023-10-16T00:00:00Z"),
"end_date": ISODate("2023-10-25T00:00:00Z"),
"status": "запланировано",
"created_at": ISODate("2023-09-28T00:00:00Z"),
"updated_at": ISODate("2023-10-01T00:00:00Z"),
"workers": [
{
"user_id": ObjectId("60c72b2f9c3d4d1234567894"),
"name": "Анна Сидорова"
},
{
"user_id": ObjectId("60c72b2f9c3d4d1234567895"),
"name": "Сергей Кузнецов"
}
]
}
]
}
{
"chatId": "64ff1234a1b2c3d4e5f67890",
"sender": "user1_id",
"receiver": "user2_id",
"content": "Привет, как дела?",
"status": "unread",
"timestamp": "2024-11-08T12:31:00Z"
}
{
"_id": "ObjectId", // Уникальный идентификатор закупки
"item_name": "String", // Наименование товара
"quantity": "Number", // Количество товара
"price": "Number", // Цена товара
"created_by": "ObjectId", // Идентификатор пользователя, создавшего закупку
"created_date": "ISODate", // Дата создания закупки
"updated_at": "ISODate", // Дата последнего обновления
"delivery_date": "ISODate", // Дата поставки товара
"project_id": "ObjectId" // Идентификатор связанного проекта
}
{
"_id": ObjectId("60c72b2f9c3d4d1234567890"),
"name": "Задержка поставок",
"description": "Возможная задержка поставок оборудования, что может привести к задержке проекта.",
"created_at": ISODate("2023-01-01T00:00:00Z"),
"updated_at": ISODate("2023-01-15T00:00:00Z")
}
{
"_id": ObjectId("60c72b2f9c3d4d1234567890"),
"user_id": ObjectId("60c72b2f9c3d4d1234567891"),
"project_id": ObjectId("60c72b2f9c3d4d1234567892"),
"created_at": ISODate("2023-01-01T00:00:00Z"),
"updated_at": ISODate("2023-01-15T00:00:00Z")
}
{
"_id": "ObjectId('64ff1234a1b2c3d4e5f67890')",
"participants": {
"user1_id": {
"name": "Иван Иванов",
"lastSeen": ISODate("2024-11-08T12:00:00Z")
},
"user2_id": {
"name": "Мария Петрова",
"lastSeen": ISODate("2024-11-08T12:05:00Z")
}
},
"lastMessage": {
"content": "Последнее сообщение",
"sender": "user1_id",
"status": "unread",
"timestamp": ISODate("2024-11-08T12:30:00Z")
},
"createdAt": ISODate("2024-11-08T10:00:00Z"),
"updatedAt": ISODate("2024-11-08T12:30:00Z")
}
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
async def authenticate_user(username: str, password: str):
user_collection = database.get_collection("users")
user = await user_collection.find_one({"username": username})
if user and verify_password(password, user["password"]):
return user
else:
return None
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
async def create_user(user: User):
user_collection = database.get_collection("users")
user.password = hash_password(user.password)
user.created_at = datetime.utcnow()
user.updated_at = datetime.utcnow()
result = await user_collection.insert_one(user.dict(by_alias=True))
return result.inserted_id
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
class Project(BaseModel):
_id: ObjectId = Field(default_factory=ObjectId, alias="_id")
name: str
description: str
start_date: datetime
end_date: datetime
status: str
created_at: datetime
updated_at: datetime
contacts: Dict[str, dict] = {}
stages: Dict[str, dict] = {}
risks: Dict[str, dict] = {}
procurements: Dict[str, dict] = {}
# ...
async def create_project(project: Project):
project_collection = database.get_collection("projects")
project.created_at = datetime.utcnow()
project.updated_at = datetime.utcnow()
result = await project_collection.insert_one(project.dict(by_alias=True))
return result.inserted_id
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
class Task(BaseModel):
_id: ObjectId = Field(default_factory=ObjectId, alias="_id")
name: str
description: str
start_date: datetime
end_date: datetime
status: str
created_at: datetime
updated_at: datetime
workers: Dict[str, Worker] = {}
# ...
async def create_task(task: Task):
task_collection = database.get_collection("tasks")
task.created_at = datetime.utcnow()
task.updated_at = datetime.utcnow()
result = await task_collection.insert_one(task.dict(by_alias=True))
return result.inserted_id
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
async def add_worker_to_task(task_id: str, worker: Worker):
task_collection = database.get_collection("tasks")
result = await task_collection.update_one(
{"_id": ObjectId(task_id)},
{"$set": {f"workers.{str(worker.user_id)}": worker.dict(by_alias=True)}}
)
return result.modified_count
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
class LastMessage(BaseModel):
content: str
sender: str
status: str
timestamp: datetime
class Participant(BaseModel):
name: str
lastSeen: datetime
class Chat(BaseModel):
_id: ObjectId = Field(default_factory=ObjectId, alias="_id")
participants: Dict[ObjectId, Participant]
lastMessage: LastMessage
createdAt: datetime
updatedAt: datetime
# ...
class Message(BaseModel):
_id: ObjectId = Field(default_factory=ObjectId, alias="_id")
chatId: ObjectId
sender: str
receiver: str
content: str
status: str
timestamp: datetime
# ...
async def create_chat(chat: Chat):
chat_collection = database.get_collection("chats")
chat.createdAt = datetime.utcnow()
chat.updatedAt = datetime.utcnow()
result = await chat_collection.insert_one(chat.dict(by_alias=True))
return result.inserted_id
async def create_message(message: Message):
message_collection = database.get_collection("messages")
result = await message_collection.insert_one(message.dict(by_alias=True))
return result.inserted_id
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
async def update_last_message(chat_id: str, message: Message):
chat_collection = database.get_collection("chats")
last_message = LastMessage(
content=message.content,
sender=message.sender,
status=message.status,
timestamp=message.timestamp
)
result = await chat_collection.update_one(
{"_id": ObjectId(chat_id)},
{"$set": {"lastMessage": last_message.dict(by_alias=True), "updatedAt": datetime.utcnow()}}
)
return result
async def create_message_route(message_create: Message):
message = Message(**message_create.dict())
message_id = await create_message(message)
await update_last_message(message.chatId, message)
return {"_id": message_id, **message.dict()}
MONGO_DETAILS = "mongodb://localhost:27017"
client = AsyncIOMotorClient(MONGO_DETAILS)
database = client['repair-db']
# ...
async def get_chats_for_user(user_id: str):
chat_collection = database.get_collection("chats")
chats = await chat_collection.find({"participants.{}".format(user_id): {"$exists": True}}).to_list(None)
return chats
async def get_unread_messages():
message_collection = database.get_collection("messages")
messages = await message_collection.find({"status": "unread"}).to_list(None)
return messages
client = MongoClient('mongodb://localhost:27017/')
db = client['repair-db']
# ...
def create_risk(name, description):
risks_collection = db['risks']
risk = {
"_id": ObjectId(),
"name": name,
"description": description,
"created_at": datetime.utcnow(),
"updated_at": datetime.utcnow()
}
risks_collection.insert_one(risk)
create_risk("Risk 1", "Description of Risk 1")
client = MongoClient('mongodb://localhost:27017/')
db = client['repair-db']
# ...
def create_procurement(item_name, quantity, price, project_id):
procurements_collection = db['procurements']
procurement = {
"_id": ObjectId(),
"item_name": item_name,
"quantity": quantity,
"price": price,
"created_date": datetime.utcnow(),
"updated_at": datetime.utcnow(),
"project_id": project_id
}
procurements_collection.insert_one(procurement)
create_procurement("Item 1", 10, 100.0, ObjectId())
async def get_total_procurement_sums():
procurement_collection = database.get_collection("procurements")
pipeline = [
{
"$group": {
"_id": None,
"total_sum": {"$sum": {"$multiply": ["$quantity", "$price"]}}
}
},
{
"$project": {
"_id": 0,
"total_sum": 1
}
}
]
result = await procurement_collection.aggregate(pipeline).to_list(None)
return result
client = MongoClient('mongodb://localhost:27017/')
db = client['repair-db']
# ...
def get_statistics(stat_type, project_ids, start_date, end_date):
if stat_type not in ['risks', 'procurements']:
raise ValueError("Неподдерживаемый тип статистики. Поддерживаемые типы: 'risks', 'procurements'.")
query = {
'project_id': {'$in': [ObjectId(pid) for pid in project_ids]},
'created_date': {
'$gte': start_date,
'$lte': end_date
}
}
if stat_type == 'risks':
collection = db['risks']
elif stat_type == 'procurements':
collection = db['procurements']
statistics = collection.find(query)
return list(statistics)
roject_ids = ['60f1b8d4e138234068a9099a', '60f1b8d4e138234068a9099b']
start_date = datetime(2023, 1, 1)
end_date = datetime(2023, 12, 31)
# Получение статистики по рискам
risk_statistics = get_statistics('risks', project_ids, start_date, end_date)
# Получение статистики по закупкам
procurement_statistics = get_statistics('procurements', project_ids, start_date, end_date)
import json
from pymongo import MongoClient
from datetime import datetime
from bson import ObjectId
client = MongoClient('mongodb://localhost:27017/')
db = client['repair-db']
projects_collection = db['projects']
def convert_date_strings(data):
for item in data:
for key in ['start_date', 'end_date', 'created_at', 'updated_at']:
if key in item:
try:
item[key] = datetime.strptime(item[key], '%Y-%m-%dT%H:%M:%SZ')
except ValueError:
raise ValueError(f"Некорректный формат даты для поля {key}: {item[key]}")
if '_id' in item:
item['_id'] = ObjectId(item['_id'])
return data
def validate_data(data):
required_fields = ['_id', 'name', 'description', 'start_date', 'end_date', 'status', 'created_at', 'updated_at']
for item in data:
for field in required_fields:
if field not in item:
raise ValueError(f"Отсутствует обязательное поле {field} в элементе: {item}")
return data
with open('data.json', 'r') as file:
data = json.load(file)
data = validate_data(data)
data = convert_date_strings(data)
projects_collection.insert_many(data)
import json
from pymongo import MongoClient
from datetime import datetime
from bson import ObjectId
client = MongoClient('mongodb://localhost:27017/')
db = client['repair-db']
projects_collection = db['projects']
def convert_datetime_to_string(data):
for item in data:
for key in ['start_date', 'end_date', 'created_at', 'updated_at']:
if key in item and isinstance(item[key], datetime):
item[key] = item[key].strftime('%Y-%m-%dT%H:%M:%SZ')
if '_id' in item:
item['_id'] = str(item['_id'])
return data
data = list(projects_collection.find())
data = convert_datetime_to_string(data)
with open('exported_projects.json', 'w') as file:
json.dump(data, file, indent=4)
Реляционная модель данных обычно имеет меньший удельный объем информации по сравнению с нереляционной. Это связано с тем, что в нереляционных системах данные часто дублируются для уменьшения числа обращений к базе данных, что приводит к избыточности. В реляционной модели используются разные таблицы для хранения связанных данных, что требует больше времени на объединение (JOIN) при сложных запросах, но обеспечивает более компактное хранение и минимизацию дублирования. Выбор между реляционной и нереляционной моделями зависит от требований системы, таких как скорость доступа или целостность данных.
-
для модели User:
2578 байт(NoSQL)
|2527 байт(SQL)
-
для модели Project:
12062 байт(NoSQL)
|11253 байт(SQL)
-
для модели Task:
3130 байт(NoSQL)
|1063 байт(SQL)
-
для модели Message:
570 байт(NoSQL)
|563 байт(SQL)
-
для модели Procurement:
556 байт(NoSQL)
|546 байт(SQL)
В нереляционной модели количество запросов для выполнения юзкейсов остаётся неизменным, независимо от количества объектов в базе данных. В реляционной модели с увеличением числа объектов количество запросов может возрастать.
-
Регистрация/Авторизация:
1 запрос в (SQL)
vs1 запрос (NoSQL)
-
Создание проекта:
1 запрос в (SQL)
vs1 запрос (NoSQL)
-
Создание риска:
1 запрос в (SQL)
vs1 запрос (NoSQL)
-
Поиск сообщений:
1 запрос в (SQL)
vs1 запрос (NoSQL)
-
Получение статистики:
1 запрос в (SQL)
vs1 запрос (NoSQL)
-
Регистрация/Авторизация:
1 (SQL)
vs1(NoSQL)
-
Создание проекта:
1 (SQL)
vs1 (NoSQL)
-
Создание риска:
1 (SQL)
vs1 (NoSQL)
-
Поиск сообщений:
1 (SQL)
vs1 (NoSQL)
-
Получение статистики:
1 (SQL)
vs1 (NoSQL)
На основе проведённого анализа можно сделать следующие выводы для данного проекта:
-
Удельный объём информации: Реляционная модель данных обладает меньшим объёмом хранения, чем нереляционная. Это позволяет более эффективно использовать дисковое пространство за счёт минимизации дублирования данных.
-
Количество запросов: Обе модели демонстрируют приблизительно одинаковые результаты по количеству запросов, необходимых для выполнения основных юзкейсов, что свидетельствует о схожей производительности при обращении к данным.
-
Число используемых коллекций: Нереляционная модель позволяет уменьшить количество задействованных коллекций за счёт встроенной поддержки сложных структур данных, что может упростить некоторые аспекты разработки.
Несмотря на то, что MongoDB (нереляционная модель) может упростить архитектуру запросов и снизить нагрузку на уровне приложений, она требует более тщательного управления бизнес-логикой в самой базе данных. Это может привести к усложнению разработки и снижению гибкости при масштабировании приложения.
С учётом этих факторов реляционная модель на базе SQL выглядит предпочтительнее для данного проекта, так как она позволяет более эффективно использовать ресурсы и облегчает поддержку приложения в долгосрочной перспективе.