Skip to content

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

Melkumyants Danila edited this page Oct 31, 2024 · 5 revisions

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

MongoDB

nosql

Коллекции и сущности

Пусть n = 200 - максимальная длина строки.

User

Назначение: хранение информации о пользователе.

{
"id" : ObjectId(), 
"mail" : "string",
"password" : "string",
"sex" : "string",
"birth_date": ISODate(),
"name" : "string",
"surname" : "string",
"phone_number" : "string",
"meetings" : [
    {
    "id" : ObjectId(), 
    "time" : ISODate(),
    "psychologist_id" : ObjectId(),
    "status" : "string",
    }
],
"reviews" : [ObjectId()],
"transactions" : [ObjectId()],
}

Psychologist

Назначение: хранение информации о психологе.

{
"user" : 
    {
    "id" : ObjectId(), 
    "mail" : "string",
    "password" : "string",
    "sex" : "string",
    "birth_date": ISODate(),
    "name" : "string",
    "surname" : "string",
    "phone_number" : "string",
    "balance" : "number"
    "meetings" : [
        {
        "id" : ObjectId(), 
        "time" : ISODate(),
        "psychologist_id" : ObjectId(),
        "status" : "string",
        }
    ],
    "reviews" : [ObjectId()],
    },
"price" : "number",
"address" : "string",
"meeting_format" : "string",
"education": [{ "institution": "string", "degree": "string", "year_graduated": ISODate() }],
"work_experience": [{ "position": "string", "place": "string", "years": [ISODate()] }],    
"language" : "string",
"articles" : [ObjectId()]
}

Meeting

Назначение: хранение информации о сессии клиента с психологом.

{
"id" : ObjectId(), 
"time" : ISODate(),
"user_id" : ObjectId(),
"psychologist_id" : ObjectId(),
"status" : "scheduled" | "completed" | "canceled",
}

Review

Назначение: хранение информации об отзыве о психологе.

{
"id" : ObjectId(),
"content" : "string",
"user_id" : ObjectId(),
"psychologist_id" : ObjectId(),
"created_at": ISODate(),
"rating": "number"
}

Article

Назначение: хранение информации о статьях.

{
"id" : ObjectId(),
"content" : "string",
"psychologist_id" : ObjectId(),
"created_at": ISODate(),
"updated_at": ISODate()
}

Transactions

Назначение: хранение информации о транзакциях пользователя.

{
    "id": ObjectId(),
    "user_id": ObjectId(),
    "amount": "number",
    "created_at": ISODate()
}

Оценка удельного объема информации

Пусть пользователь будет создавать 1 отзыв, 1 встречу, а психолог будет писать 1 статью. И предположим, что на 1 психолога приходится 10 обычных пользователей.

User: 12 + n + 20 + 1 + 8 + 25 + 25 + 11 + 8 + 54 = 356

Psychologist: 12 + n + n + 7 + n + 8 + n + n + 356 + 12 = 1399

Meeting: 12 + 12 + 12 + 8 + 10 = 54

Review: 12 + 4 * n + 12 + 12 = 836

Article: 12 + 100 * n + 12 = 20024

Тогда при количестве пользователей равным $N$ удельный объем:

$V(N) = (356 + 836 + 54 + (1399 + 20024) / 10) * N = 3389 * N $

Избыточность данных

User: meeting, review_id Psychologist: user, article_id Meeting: user_id, psychologist_id

Тогда чистый объем:

$V_{clean}(N) = (290 + 30 + 836 + (1043 + 20004) / 10) * N = 3261 * N $

Тогда избыточность:

$\frac{V(N)}{V_{clean}(N)} = \frac{3389 * N}{3261 * N} \approx 1.039 $

Направление роста модели

Для создания любой модели обязательно существование модели User. При создании сущности Psychologist, в нее дублируется сущность User. При добавлении сущности Meeting, она дублируется в User. При добавлении Review или Article, в User добавляются их Object_Id.

Примеры данных

Модель User

{
"id" : 145341129389203813049493003, 
"mail" : "0@mail",
"password" : "123456",
"sex" : "m",
"age" : 30,
"name" : "jo",
"surname" : "jones",
"phone_number" : "79998887766",
"balance" : 10000
"meetings" : [],
"reviews" : [],
}

Модель Psychologist

{
    "user": {
        "id": ObjectId("654321abcdef1234567890ab"),
        "mail": "[email protected]",
        "password": "hashed_password",
        "sex": "female",
        "birth_date": ISODate("1985-04-15T00:00:00Z"),
        "name": "Anna",
        "surname": "Smith",
        "phone_number": "+1234567890",
        "balance": 2000,
        "meetings": [
            {
                "id": ObjectId("607f1f77bcf86cd799439011"),
                "time": ISODate("2023-10-31T09:00:00Z"),
                "psychologist_id": ObjectId("654321abcdef1234567890ab"),
                "status": "completed"
            }
        ],
        "reviews": [ObjectId("607f1f77bcf86cd799439022")]
    },
    "price": 1000,
    "address": "",
    "meeting_format": "online",
    "education": [
        {
            "institution": "",
            "degree": "",
            "year_graduated": ISODate("2010-06-15T00:00:00Z")
        },
    ],
    "work_experience": [
        {
            "position": "Child Psychologist",
            "place": "School District 15",
            "years": [ISODate("2011-09-01T00:00:00Z"), ISODate("2018-06-01T00:00:00Z")]
        },
    ],
    "language": "English",
    "articles": [ObjectId("607f1f77bcf86cd799439033")]
}

Модель Meeting

{
    "id": ObjectId("607f1f77bcf86cd799439044"),
    "time": ISODate("2024-11-01T15:30:00Z"),
    "user_id": ObjectId("123456abcdef6543210980ab"),
    "psychologist_id": ObjectId("654321abcdef1234567890ab"),
    "status": "scheduled"
}

Модель Review

{
    "id": ObjectId("607f1f77bcf86cd799439055"),
    "content": "",
    "user_id": ObjectId("123456abcdef6543210980ab"),
    "psychologist_id": ObjectId("654321abcdef1234567890ab"),
    "created_at": ISODate("2024-10-30T12:45:00Z"),
    "rating": 5
}

Модель Article

{
    "id": ObjectId("607f1f77bcf86cd799439066"),
    "content": "...",
    "psychologist_id": ObjectId("654321abcdef1234567890ab"),
    "created_at": ISODate("2024-09-15T08:30:00Z"),
    "updated_at": ISODate("2024-10-01T10:00:00Z")
}

Модель Transactions

{
    "id": ObjectId("607f1f77bcf86cd799439077"),
    "user_id": ObjectId("123456abcdef6543210980ab"),
    "amount": 1000,
    "created_at": ISODate("2024-10-31T13:15:00Z")
}

Примеры запросов

Текст запросов Количество запросов для совершения юзкейсов в зависимости от числа объектов в БД и прочих параметров Количество задействованных коллекций (если есть)

Поиск психолога по имени

1. Текст запроса

db.users.find({
  role: "psychologist",
  name: { $regex: "имя_психолога", $options: "i" }
})

2. Количество запросов для совершения юзкейсов

  • 1 запрос.

3. Количество задействованных коллекций

  • 1 коллекция: users.

Получение статьи по ID

1. Текст запроса

db.articles.findOne({ _id: ObjectId("id_статьи") })

2. Количество запросов для совершения юзкейсов

  • 1 запрос.

3. Количество задействованных коллекций

  • 1 коллекция: articles.

Получение информации о пользователе

1. Текст запроса

db.users.findOne({ _id: ObjectId("id_пользователя") })

2. Количество запросов для совершения юзкейсов

  • 1 запрос.

3. Количество задействованных коллекций

  • 1 коллекция: users.

Отображение зарегистрированных встреч для конкретного пользователя

1. Текст запроса

db.meetings.find({ user_id: ObjectId("id_пользователя") })

2. Количество запросов для совершения юзкейсов

  • 1 запрос для всех случаев (маленькая, средняя, большая БД).

3. Количество задействованных коллекций

  • 1 коллекция: meetings.

Пользователь может изменить информацию о себе

1. Текст запроса

db.users.updateOne(
  { _id: ObjectId("id_пользователя") },
  { $set: { mail: "новый_email", phone_number: "новый_номер_телефона", name: "новое_имя" } }
)

2. Количество запросов для совершения юзкейсов

  • 1 запрос для всех случаев (маленькая, средняя, большая БД).

3. Количество задействованных коллекций

  • 1 коллекция: users.

6. Поиск самых загруженных

Текст запроса

db.meetings.aggregate([
    { $match: { time: { $gte: new ISODate(new Date().setMonth(new Date().getMonth() - 1)) } } },
    { $group: { _id: "$psychologist_id", sessions_count: { $sum: 1 } } },
    { $sort: { sessions_count: -1 } },
    { $limit: 10 }
]);

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: meetings.

7. Поиск самых загруженных

Текст запроса

db.transactions.aggregate([
    { $match: { timestamp: { $gte: new ISODate(new Date().setMonth(new Date().getMonth() - 1)) }, type: "credit" } },
    { $group: { _id: "$user_id", total_earnings: { $sum: "$amount" } } },
    { $sort: { total_earnings: -1 } },
    { $limit: 10 }
]);

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: transactions.

8. Поиск клиентов, у которых больше всего отмененных сессий

Текст запроса

db.meetings.aggregate([
    { $match: { status: "canceled" } },
    { $group: { _id: "$user_id", canceled_sessions: { $sum: 1 } } },
    { $sort: { canceled_sessions: -1 } },
    { $limit: 10 }
]);

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: meetings.

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

PostgreSQL

sql

Коллекции и сущности

Пусть n = 200 - максимальная длина строки.

User

Назначение: хранение информации о пользователе.

  • id int(4)
  • mail(n)
  • password varchar(20)
  • sex varchar(1)
  • birth_date DATE
  • name text(25)
  • surname text(25)
  • phone_number varchar(11)
  • balance int(4)
  • messengers JSONB

Psychologist

Назначение: хранение информации о психологе.

  • user_id int(4)
  • price int(4)
  • address text(n)
  • meeting_format enum(varchar(7)|varchar(6))
  • education JSONB
  • work_experience JSONB
  • specialization text(n)
  • language text(n)

Meeting

Назначение: хранение информации о сессии клиента с психологом.

  • time timestamp(8)
  • user_id int(4)
  • psychologist_id int(4)
  • status ENUM ('scheduled', 'completed', 'canceled')

Review

Назначение: хранение информации об отзыве о психологе.

  • id int(4)
  • content text(4*n)
  • user_id int(4)
  • psychologist_id int(4)
  • created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  • rating INT

Article

Назначение: хранение информации о статьях.

  • id int(4)
  • content text(100*n)
  • psychologist_id int(4)
  • created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  • updated_at TIMESTAMP

Transactions

Назначение: хранение транзакций пользователя.

  • id int(4)
  • user_id int(4)
  • amount int
  • created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

Оценка удельного объема информации

User: 4 + n + 20 + 1 + 4 + 25 + 25 + 11 + 4 = 294

Psychologist: 4 + n + n + 7 + n + 4 + n + n = 1019

Meeting: 8 + 4 + 4 + 10 = 26

Review: 4 + 4 * n + 4 + 4 = 812

Article: 4 + 100 * n + 4 = 20008

Пусть пользователь будет создавать 1 отзыв, 1 встречу, а психолог будет писать 1 статью. И предположим, что на 1 психолога приходится 10 обычных пользователей. Тогда при количестве пользователей равным $N$ удельный объем:

$V(N) = (294 + 26 + 812 + (1019 + 20008 + 294) / 10) * N = 3276 * N $

Избыточность данных

Psychologist: user_id int(4) Meeting: user_id int(4), psychologist_id int(4) Review: user_id int(4), psychologist_id int(4) Article: psychologist_id int(4)

Тогда чистый объем:

$V_{clean}(N) = (294 + 18 + 804 + (1015 + 20004 + 294) / 10) * N = 3259 * N $

Тогда избыточность:

$\frac{V(N)}{V_{clean}(N)} = \frac{3276 * N}{3259 * N} \approx 1.005 $

Направление роста модели

Для создания любой модели обязательно существование модели User. При добавлении других моделей дополнительные модели создаваться не будут.

Примеры данных

Таблица User

id mail password sex age name surname phone_number balance
0 0@mail 123456 m 30 jo jones 79998887766 10000
1 0@mail qwerty w 27 sue sunes 75554443322 120000

Таблица Psychologist

user_id price address meeting_format education work_experience specialization language
0 3000 My Street, 8 online MIT 5 Gestalt therapy russian

Примеры запросов

Текст запросов Количество запросов для совершения юзкейсов в зависимости от числа объектов в БД и прочих параметров Количество задействованных коллекций (если есть)

1. Поиск психолога по имени

Текст запроса

SELECT * 
FROM users
WHERE name ILIKE 'имя_психолога'
AND id IN (SELECT user_id FROM psychologists);

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 2 таблицы: users, psychologists.

2. Получение статьи по id

Текст запроса

SELECT * 
FROM articles
WHERE id = id_статьи;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: articles.

3. Получение информации о пользователе

Текст запроса

SELECT * 
FROM users
WHERE id = id_пользователя;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: users.

4. Отображение зарегистрированных встреч для конкретного пользователя

Текст запроса

SELECT * 
FROM meetings
WHERE user_id = id_пользователя;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: meetings.

5. Пользователь может изменить информацию о себе

Текст запроса

UPDATE users
SET mail = 'новый_email', phone_number = 'новый_номер_телефона', name = 'новое_имя'
WHERE id = id_пользователя;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: users.

6. Поиск самых загруженных

Текст запроса

SELECT psychologist_id, COUNT(*) AS sessions_count
FROM meetings
WHERE time >= (CURRENT_DATE - INTERVAL '1 month')
GROUP BY psychologist_id
ORDER BY sessions_count DESC
LIMIT 10;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: meetings.

7. Поиск самых загруженных

Текст запроса

SELECT psychologist_id, SUM(amount) AS total_earnings
FROM transactions
WHERE timestamp >= (CURRENT_DATE - INTERVAL '1 month')
GROUP BY psychologist_id
ORDER BY total_earnings DESC
LIMIT 10;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: transactions.

8. Поиск клиентов, у которых больше всего отмененных сессий

Текст запроса

SELECT user_id, COUNT(*) AS canceled_sessions
FROM meetings
WHERE status = 'canceled'
GROUP BY user_id
ORDER BY canceled_sessions DESC
LIMIT 10;

Количество запросов для совершения юзкейсов

  • 1 запрос.

Количество задействованных коллекций

  • 1 таблица: meetings.

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

1. Удельный объем информации

Реляционная модель (PostgreSQL):

  • Для сохранения объектов в реляционной модели требуется меньше памяти из-за отсутствия дублирования данных.

Нереляционная модель (MongoDB):

  • В MongoDB наблюдается некоторая избыточность данных, так как сущности, например, User и Psychologist, дублируют информацию друг друга. Это увеличивает объем хранимых данных, особенно когда психологи дублируют данные пользователей.

Вывод: В реляционной модели данные занимают меньший объем при прочих равных, так как она структурирована с минимальной избыточностью.


2. Запросы по отдельным юзкейсам

Поиск психолога по имени

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 2 таблицы (users и psychologists).

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 коллекция (users).

Вывод: MongoDB требует обращения только к одной коллекции, что может быть быстрее при меньших затратах на операции соединения.


Получение статьи по ID

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 таблица (articles).

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 коллекция (articles).

Вывод: Оба подхода идентичны по эффективности при выполнении данного запроса.


Получение информации о пользователе

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 таблица (users).

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 коллекция (users).

Вывод: Оба подхода равны по количеству запросов и эффективности.


Отображение зарегистрированных встреч для конкретного пользователя

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 таблица (meetings).

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 коллекция (users, так как встречи вложены в документ пользователя).

Вывод: В MongoDB встречи хранятся внутри документа пользователя, что позволяет избежать дополнительных обращений к коллекциям. Это упрощает запросы и может ускорить их выполнение.


Пользователь может изменить информацию о себе

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 таблица (users).

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

  • Количество запросов: 1 запрос.
  • Количество коллекций: 1 коллекция (users).

Вывод: Оба подхода идентичны по количеству запросов и эффективности.


3. Вывод

Для данного проекта наиболее подходящей будет MongoDB (NoSQL). Она обеспечивает гибкость в структуре данных, высокую производительность при работе с вложенными документами и легкость в масштабировании. Это особенно важно в условиях частых изменений в структуре данных и необходимости обрабатывать большие объемы информации, связанных с психологами, пользователями, встречами и отзывами.

Clone this wiki locally