-
Notifications
You must be signed in to change notification settings - Fork 0
Модель данных
users
{
"_id": ObjectId(), //id пользователя - 12 байт
"photo": "string", // URL фотографии пользователя - в среднем 60 байт
"login": "string", // Логин пользователя - в среднем 10 байт
"email": "string", // Почта пользователя - в среднем 30 байт
"role": "string", // Роль (админ, просто юзер) пользователя - 5 байт
"password": "string", // Пароль пользователя - 256 байт
"registred_at": ISODate(), // Дата регистрации - 8 байт
"updated_at": ISODate(), // Дата обновления профиля - 8 байт
"rates_count": integer, // Количество оценок - 4 байта
"rates":[ // Оценки пользователя - в среднем 10 оценок ~ 610 байт
{
"_id": ObjectId(), // id оценки - 12 байт
"anime_id": ObjectId(), // id аниме - 12 байт
"anime_name": "string", // название аниме - в среднем 25 байт
"date": ISODate(), // дата оценки - 8 байт
"rate": "integer", // оценка - 4 байта
}
],
"account_logs":[ // Изменения аккаунта - в среднем 5 изменений ~ 300 байт
{
"_id": ObjectId(), // id изменения - 12 байт
"date": ISODate(), // дата изменения - 8 байт
"type": "string", // тип изменения (создание, изменение ника...) - в среднем 10 байт
"description": "string", // описание - в среднем 30 байт
}
],
"reviews_count": integer, // число отзывов пользователя - 4 байта
}
anime
{
"_id": ObjectId(), // id аниме - 12 байт
"cover": "string", // url фото обложки - в среднем 60 байт
"name":"string", // название - в среднем 25 байт
"type": "string", // тип (сериал, фильм...) - в среднем 7 байт
"episodes":"string", // количество эпизодов - 2 байта
"status": "string", // статус (вышло, выходит..) - в среднем 6 байт
"year":ISODate(), // год выхода - 8 байт
"genre": "[string]", // жанр - в среднем 10 байт
"age_rating": "string", // возрастной рейтинг - в среднем 3 байта
"other_names": [string], // другие названия - в среднем по 2 названия, в среднем ~ 50 байт
"studio":"string", // студия - в среднем 15 байт
"rating":"double", // рейтинг - 8 байт
"rates_count": "integer" // количество оценок - 4 байта
"description":"string", // описание - в среднем 1000 байт
"reviews":[ // отзывы - в среднем 10 отзывов ~ 9040 байт
{
"_id": ObjectId(), // id отзыва - 12 байт
"user_id": ObjectId(), // id пользователя - 12 байт
"photo_mini": "string", // url маленького фото пользователя - в среднем 60 байт
"date": ISODate(), // дата написания - 8 байт
"rate": "integer", // оценка - 4 байта
"text": "string" // текст отзыва - в среднем 800 байт
"reccomendation": "string", // положительный/отрицательный/нейтральный отзыв - в среднем 8 байт
}
]
"negative_rev_count": "integer" // кол-во отрицательных отзывов
"positive_rev_count": "integer"// кол-во положительных отзывов
"neutral_rev_count": "integer"// кол-во нейтральных отзывов
}
review
{
"_id": ObjectId(), // id отзыва - 12 байт
"user_id": ObjectId(), // id пользователя - 12 байт
"anime_id": ObjectId(), // id аниме - 12 байт
"anime_name": "string", // название аниме - в среднем 25 байт
"anime_cover_mini":"string", // url маленькой обложки аниме - в среднем 60 байт
"date": ISODate(), // дата написания - 8 байт
"rate": "integer", // оценка - 8 байт
"text": "string", // текст отзыва - в среднем 800 байт
"reccomendation": "string", // положительный/отрицательный/нейтральный отзыв - в среднем 8 байт
}
- users - 1307 байт
Общий объем для всех пользователей: u*1307 байт, где u - количество пользователей
- anime - 10262 байт
Общий объем для всех пользователей: a*10262 байт, где a - количество аниме
- review - 945 байт
Общий объем для всех пользователей: r*945байт, где r - количество отзывов
Если выражать через количество пользователей, то получится следующая формула:
V(u) = (1307 + 945 * 10) * u + (904 * 10 * u + 1222)= 19797 * u + 1222
где u - количество пользователей, принимается в расчёт что каждый оставляет 10 отзывов
Избыточные данные:
- Отзывы в anime- можно хранить id отзывов
Формула чистого объёма:
V_clean (u) = (1307 + 945 * 10)*u + (1222 + 12 * 10) = 10757 * u + 1342
Тогда избыточность как отношение объема модели к "чистому" объему:
V(u)/V_clean (u) = 1.84
-
Рост количества пользователей: Прямопропорционально увеличивается общий объем данных пользователей
-
Рост количества аниме: Прямопропорционально увеличивается общий объем данных аниме
-
Рост количества отзывов: Прямопропорционально увеличивается общий объем данных отзывов и увеличивается по объёму сущность аниме, для которого соответственно был оставлен отзыв
{
"_id": "233ca3fb4a4fgc7fa9f5ea21",
"photo": "https://azumangaphotos.com/osaka.jpg",
"login": "Osaka1998",
"email": "Osaka2003@mail.com",
"role": "admin",
"password": "admin",
"registred_at": "2024-09-18T15:10:50",
"updated_at": "2024-09-18T15:10:50",
"rates_count": 3,
"rates":[
{
"_id":"233ca3fb4a4fgc7fa9f5ea22",
"anime_id": "233ca3fb4a4fgc7fa9f5ea23",
"anime_name": "Адзуманга",
"date": "2024-09-18T15:10:50",
"rate": 10,
}
],
"account_logs":[
{
"_id": "233ca3fb4a4fgc7fa9f5ea25",
"date": "2024-09-18T15:10:50",
"type": "rename",
"description": "Логин изменён на Osaka1998",
}
],
"reviews_count": 3,
}
{
"_id": "233ca3fb4a4fgc7fa9f5ea23",
"cover": "https://anime.com/azumanga.jpg",
"name":"Адзуманга",
"type": "TV сериал",
"episodes":"26",
"status": "Вышло",
"year":"2003-09-18T00:00:00",
"genre": ["Комедия"],
"age_rating": "PG-13",
"other_names": ["Azumanga Daioh: The Animation", "あずまんが大王 THE ANIMATION"],
"studio":"JC staff",
"rating": 8.03,
"rates_count": 16000,
"description":"Chiyo Mihama begins her high school career as one of the strangest students in her freshman class—a tiny, 10-year-old academic prodigy with a fondness for plush dolls and homemade cooking. But her homeroom teacher, Yukari Tanizaki, is the kind of person who would hijack a student's bike to avoid being late, so "strange" is a relative word. There certainly isn't a shortage of peculiar girls in Yukari-sensei's homeroom class. Accompanying Chiyo are students like Tomo Takino, an energetic tomboy with more enthusiasm than brains; Koyomi Mizuhara, Tomo's best friend whose temper has a fuse shorter than Chiyo; and Sakaki, a tall, athletic beauty whose intimidating looks hide a gentle personality and a painful obsession with cats. In addition, transfer student Ayumu Kasuga, a girl with her head stuck in the clouds, fits right in with the rest of the girls—and she has a few interesting theories about Chiyo's pigtails! Together, this lovable group of girls experience the ups and downs of school life, their many adventures filled with constant laughter, surreal absurdity, and occasionally even touching commentary on the bittersweet, temporal nature of high school.",
"reviews":[
{
"_id": "233ca3fb4a4fgc7fa9f5ea27",
"user_id": "233ca3fb4a4fgc7fa9f5ea21",
"photo_mini": "https://azumangaphotos.com/osaka_mini.jpg",
"date": "2023-09-18T10:00:00",
"rate": 10,
"text": "It seems to me that people who have seen Azumanga Daioh are divided into two groups. The first group consists of people who enjoyed it, and thought it was the best thing since sliced bread. The other consists of those that thought it was boring and nonsensical. I find myself right in the middle. It wasn’t so bad story wise – usually I’m all for “anything goes” anime. The problem I had with it was that it wasn’t as funny as I thought it would be. "
"reccomendation": "positive",
}
]
"negative_rev_count": 0,
"positive_rev_count": 1,
"neutral_rev_count": 0
}
{
"_id": "233ca3fb4a4fgc7fa9f5ea27",
"user_id": "233ca3fb4a4fgc7fa9f5ea21",
"anime_id": "233ca3fb4a4fgc7fa9f5ea24",
"anime_name": "Адзуманга",
"anime_cover_mini":"https://anime.com/azumanga_mini.jpg",
"date": "2023-09-18T10:00:00",
"rate": 10,
"text": "It seems to me that people who have seen Azumanga Daioh are divided into two groups. The first group consists of people who enjoyed it, and thought it was the best thing since sliced bread. The other consists of those that thought it was boring and nonsensical. I find myself right in the middle. It wasn’t so bad story wise – usually I’m all for “anything goes” anime. The problem I had with it was that it wasn’t as funny as I thought it would be. ",
"reccomendation": "positive",
}
db.user.find({email: "Osaka2003@mail.com", password: "admin"})
db.users.insertOne({
login: "Osaka1998",
email: "Osaka2003@mail.com",
role: "user",
password: "123",
registred_at: new Date(),
rates_count: 0,
reviews_count: 0,
account_logs:[
{
"_id": "233ca3fb4a4fgc7fa9f5ea25",
"date": new Date(),
"type": "create",
"description": "Аккаунт создан",
}
]
})
db.user.updateOne({_id: ObjectId('671aacc86cf54cffac86b01e')},
{
$set: {
login:"newOsaka"
},
$currentDate: { updated_at: true, "updated_at": true },
$push: {
account_logs:{
_id: ObjectId(),
"date": new Date(),
"type": "rename",
"description": "Логин изменён на newOsaka",
}
},
}
)
db.anime.find({genre: "Комедия", name: "Адзуманга", type: "TV сериал"}).limit(9)
db.anime.aggregate([{$project: { count: { $size:"$reviews" }}}
, { $sort: { count: -1 } }
])
db.anime.aggregate([{$project: { count: { $size:"$reviews" }}}
, { $sort: { count: 1 } }
])
db.anime.aggregate([
{
$match: {_id: "233ca3fb4a4fgc7fa9f5ea23"}
},
{
$set: {rates_count: {$add: ["$rates_count", 1]}}
},
{
$set: {
rating: {$divide: [ { $add: [ { $multiply: ["$rating", "$rates_count"] }, 10] } ,"$rates_count" ]}
}
},
{
$merge: {
into: "anime",
whenMatched: "merge"
}
}
])
db.user.updateOne({_id: "233ca3fb4a4fgc7fa9f5ea21"}, {$push : {rates: { _id: ObjectId(), anime_id: "233ca3fb4a4fgc7fa9f5ea23",anime_name: "Anime",date: new Date(), rate: 7,} }, $inc: {rates_count: 1} })
db.anime.aggregate([
{
$match: {_id: "233ca3fb4a4fgc7fa9f5ea23"}
},
{
$set: {
rating: {$divide: [ { $subtract: [{$add: [ { $multiply: ["$rating", "$rates_count"] }, 10]}, 7] } ,"$rates_count" ]}
}
},
{
$merge: {
into: "anime",
whenMatched: "merge"
}
}
])
db.user.updateOne({_id: "233ca3fb4a4fgc7fa9f5ea21", "rates._id": "233ca3fb4a4fgc7fa9f5ea29"}, {$set : {rates.$.rate: 7, rates.$.date: new Date()} } })
db.review.insertOne( {
user_id: "233ca3fb4a4fgc7fa9f5ea21",
anime_id: "233ca3fb4a4fgc7fa9f5ea23",
anime_name: "Anime",
anime_cover_mini:"https://anime.com/anime_mini.jpg",
date: new Date(),
rate: 7,
text: "good"
reccomendation: "positive"
})
db.anime.updateOne({_id: "233ca3fb4a4fgc7fa9f5ea23"},
{$push : {reviews: { _id: ObjectId(), user_id: "233ca3fb4a4fgc7fa9f5ea21",
photo_mini:"https://anime.com/me_mini.jpg",
date: new Date(),
rate: 7,
text: "good",
reccomendation: "positive"} },$inc: { positive_rev_count: 1} })
db.user.updateOne({_id:"233ca3fb4a4fgc7fa9f5ea21"},{$inc: {reviews_count: 1}} )
db.anime.updateOne({_id: "233ca3fb4a4fgc7fa9f5ea23", "reviews._id": "233ca3fb4a4fgc7fa9f5ea27"}, {$set : {reviews.$.text: "norm" } ,$currentDate: { updated_at: true, date: true } })
db.review.updateOne({_id: "233ca3fb4a4fgc7fa9f5ea27"}, {$set : {text: "norm" } ,$currentDate: { updated_at: true, date: true } })
db.anime.deleteOne({_id:"233ca3fb4a4fgc7fa9f5ea23", "rewirws._id": "671aba5d6cf54cffac86b024"})
db.anime.updateOne({_id:"233ca3fb4a4fgc7fa9f5ea23"}, {$inc: {positive_rev_count: -1}})
db.review.deleteOne({_id: "671aba5d6cf54cffac86b024"})
db.review.find({user_id: "233ca3fb4a4fgc7fa9f5ea21"}).limit(2)
db.user.find().sort({registred_date: 1}).limit(5)
db.user.find().sort({reviews_count: 1}).limit(5)
db.user.find().sort({reviews_count: -1}).limit(5)
db.user.aggregate([
{
$match: {
_id: "233ca3fb4a4fgc7fa9f5ea21",
}
},
{
$lookup: {
from: "review",
localField: "_id",
foreignField: "user_id",
as: "reviews"
}
},
{
$project: {
actions: {$concatArrays: ["$rates", "$account_logs", "$reviews"]}
}
},
{ $unwind: "$actions" },
{$sort : {
"actions.date": -1}}
])
db.anime.aggregate([
{
$project: {
positive_rev_count: 1,
negative_rev_count: 1,
difference: { $abs: { $subtract: ["$positive_rev_count", "$negative_rev_count"] } }
}
},
{
$sort: { difference: 1 }
}
]);
db.user.aggregate([
{
$match: {_id: "233ca3fb4a4fgc7fa9f5ea21"}
},
{ $set: {rates_count:{ $size:"$rates" } } }
,
{
$merge: {
into: "user",
whenMatched: "merge"
}
}
])
db.user.aggregate([
{
$match: {
_id: "233ca3fb4a4fgc7fa9f5ea21",
}
},
{
$lookup: {
from: "review",
localField: "_id",
foreignField: "user_id",
as: "reviews"
}
},
{ $set: {reviews_count:{ $size:"$reviews" } } },
{
$project: {
"reviews_count": "$reviews_count",
}
},
{
$merge: {
into: "user",
whenMatched: "merge"
}
}
])
db.anime.aggregate([
{
$match: {
_id: "233ca3fb4a4fgc7fa9f5ea23",
}
},
{
$lookup: {
from: "user",
localField: "_id",
foreignField: "rates.anime_id",
as: "rates"
}
},
{
$project: {
"rates": "$rates.rates",
}
},
{ $unwind: "$rates" },
{ $unwind: "$rates" },
{
$match: {
"rates.anime_id": "233ca3fb4a4fgc7fa9f5ea23",
}
},
{
$group:
{
_id: "233ca3fb4a4fgc7fa9f5ea23",
r_count: {$sum: 1}
}
},
{ $set: {rates_count: "$r_count" } },
{
$project: {
"rates_count": "$rates_count",
}
},
{
$merge: {
into: "anime",
whenMatched: "merge"
}
}
])
db.anime.aggregate([
{
$match: {
_id: "233ca3fb4a4fgc7fa9f5ea23",
}
},
{
$lookup: {
from: "user",
localField: "_id",
foreignField: "rates.anime_id",
as: "rates"
}
},
{
$project: {
"rates": "$rates.rates",
}
},
{ $unwind: "$rates" },
{ $unwind: "$rates" },
{
$match: {
"rates.anime_id": "233ca3fb4a4fgc7fa9f5ea23",
}
},
{
$group:
{
_id: "233ca3fb4a4fgc7fa9f5ea23",
sumrate: { $sum: "$rates.rate" },
count: {$sum: 1}
}
},
{ $set: {rating: {$divide: ["$sumrate", "$count"] } } },
{
$project: {
"rating": "$rating",
}
},
{
$merge: {
into: "anime",
whenMatched: "merge"
}
}
])
Назначение: хранение информации об аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
-
cover: VARCHAR(N + 1)
-
id_type: INT(4)
-
episodes: INT(4)
-
date: DATETIME(8)
-
id_genre: INT(4)
-
id_age_rating: INT(4)
-
id_other_names: INT(4)
-
id_studio: INT(4)
-
rating: DOUBLE(8)
-
rates_count: INT(4)
-
description: VARCHAR(N + 1)
-
id_reviews: INT(4)
Назначение: хранение информации о жанрах аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение: хранение информации о типах аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение: хранение информации о возрастных рейтингах аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение: хранение информации о других названиях аниме.
Поля:
-
id: INT(4)
-
id_other_names: INT(4)
-
name: VARCHAR(N + 1)
Назначение коллекции: хранение информации о студиях-производителях аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение коллекции: хранение информации о статусе, в котором сейчас находится данное аниме.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение: хранение информации о зарегистрированных пользователях приложения
Поля:
-
id: INT(4)
-
photo: VARCHAR(N + 1)
-
login: VARCHAR(N + 1)
-
password: VARCHAR(N + 1)
-
email: VARCHAR(N + 1)
-
id_role: INT(4)
-
registred_at: DATETIME(8)
-
updated_at: DATETIME(8)
Назначение: хранение логов действий пользователя со своим профилем в приложении.
Поля:
-
id: INT(4)
-
date: DATETIME(8)
-
id_type: INT(4)
-
description: VARCHAR(N + 1)
-
id_user: INT(4)
Назначение: хранение типов действий пользователя со своим профилем.
Поля:
-
id: INT(4)
-
name: VARCHAR(N + 1)
Назначение: хранение информации об отзывах, оставленных пользователями на аниме.
Поля:
-
id: INT(4)
-
id_user: INT(4)
-
id_anime: INT(4)
-
date: DATETIME(8)
-
rate: DOUBLE(8)
-
text: VARCHAR(N + 1)
-
id_reccomendation: INT(4)
Назначение: хранение отзывов на аниме, оставленных пользователями.
Поля:
-
id: INT(4)
-
reccomendation: VARCHAR(N + 1)
Пусть N = 100 символам, где каждый символ занимает 1 байт памяти, тогда каждая запись в коллекциях будет занимать следующие объемы места:
-
Anime: 4 * 9 + 8 * 2 + (N + 1) * 3 = 355 (байт)
-
Genres: 4 + (N + 1) = 105 (байт)
-
Types_Anime: 4 + (N + 1) = 105 (байт)
-
Age_Ratings: 4 + (N + 1) = 105 (байт)
-
Other_Names: 4 + (N + 1) = 105 (байт)
-
Studios: 4 * 2 + (N + 1) = 109 (байт)
-
Users: 4 * 2 + 8 * 2 + (N + 1) * 4 = 428 (байт)
-
Accounts_Logs: 4 * 2 + 8 + (N + 1) = 117 (байт)
-
Types_Update: 4 + (N + 1) = 105 (байт)
-
Reviews: 4 * 4 + 8 * 2 + (N + 1) = 133 (байт)
-
Reccomendations: 4 + (N + 1) = 105 (байт)
Предположительно коллекции:
Genres, Types_Anime, Age_Ratings, Other_Names, Studios, Types_Update будут иметь около 20 записей;
коллекция Anime будет иметь около 10000 записей;
коллекция Accounts_Logs будет иметь 1000 записей на каждого пользователя;
Коллекции Reviews и Reccomendations будут иметь по 10 записей на каждого пользователя.
При количестве пользователей U имеем следующий объем занятого места:
V(U) = 10000 * 355 + 20 * 105 + 20 * 105 + 20 * 105 + 10 * 105 + 10 * 109 + U * 428 + 1000 * U * 117 + 20 * 105 + 10 * 10000 * U * 133 + 10 * 10000 * U * 105.
После приведения подобных слагаемых получим следующее выражение:
V(U) = 23917428 * U + 3560540 (байт)
Выразим полученный результат в Мбайт:
V(U) = 22.8 * U + 3.4 (Мбайт)
Ниже представлены коллекции, а затем их поля, являющиеся избыточными:
-
Anime: id_type, id_genre, id_age_rating, id_other_names, id_studio, id_reviews: 4 * 6 * 10000 = 240000 (байт)
-
Other_Names: id_other_names: 4 * 20 = 80 (байт)
-
User: id_role, id_type: U * 4 * 2 = 8 * U (байт)
-
Accounts_Logs: id_type: 1000 * 4 * U = 4000 * U (байт)
-
Reviews: id_user, id_anime, id_reccomendation: 2 * 4 * U * 10 = 80 * U (байт)
-
Итоговая избыточность модели: 240000 + 80 + 8 * U + 4000 * U + 80 * U = 4088 * U + 240000
Больший коэффициент зависящий от числа пользователей чем свободный член позволяет сделать допущение и пренебречь свободным членом, тогда формула избыточности имеет вид:
Линейный рост сущностей будет при росте числа объектов следующих сущностей:
-
Genres
-
Types_Anime
-
Age_Ratings
-
Other_Names
-
Studios
-
Types_Update
-
Role
При росте количества объектов сущности Anime будет рост количества объектов сущностей Reviews и Reccomendations.
При росте количества объектов сущности Users будет расти количество объектов сущностей Reviews, Reccomendations, Accounts_Logs.
id | name |
---|---|
1 | Авангард |
2 | Спорт |
3 | Экшен |
4 | Драма |
5 | Триллер |
6 | Комедия |
7 | Повседневность |
8 | Фантастика |
9 | Приключения |
10 | Тайна |
11 | Романтика |
12 | Ужасы |
13 | Фэнтэзи |
id | name |
---|---|
1 | TV |
2 | Special |
3 | Ova |
4 | Movie |
id | name |
---|---|
1 | G |
2 | PG |
3 | PG-13 |
4 | R-17 |
5 | R+ |
id | id_other_names | name |
---|---|---|
1 | 1 | name1 |
2 | 2 | name3 |
3 | 1 | name4 |
4 | 1 | name3 |
5 | 3 | name1 |
id | name |
---|---|
1 | studio_1 |
2 | studio_2 |
3 | studio_3 |
4 | studio_4 |
5 | studio_5 |
id | name |
---|---|
1 | Закончено |
2 | Сейчас выходит |
3 | Еще не вышло |
id | name | cover | id_type | episodes | date | id_genre | id_age_rating | id_other_names | id_studio | rating | id_status | description | id_reviews |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | name_1 | url_1 | 2 | 35 | 15.10.2019 | 3 | 2 | 1 | 5 | 5.8 | 3 | value_1 | 1 |
2 | name_2 | url_2 | 1 | 21 | 19.06.2003 | 2 | 5 | 2 | 3 | 7.1 | 1 | value_2 | 2 |
3 | name_3 | url_3 | 3 | 12 | 01.09.2024 | 1 | 4 | 3 | 4 | 10.0 | 2 | value_6 | 1 |
id | photo | login | password | role | registered_at | updated_at | |
---|---|---|---|---|---|---|---|
1 | user1_photo.jpg | user1 | pass1234 | user1@example.com | Пользователь | 2023-10-10 12:00:00 | 2024-01-05 09:00:00 |
2 | user2_photo.jpg | user2 | pass2345 | user2@example.com | Администратор | 2023-11-15 14:30:00 | 2024-02-20 10:15:00 |
3 | user3_photo.jpg | user3 | pass3456 | user3@example.com | Пользователь | 2023-12-20 16:45:00 | 2024-03-25 11:45:00 |
4 | user4_photo.jpg | user4 | pass4567 | user4@example.com | Пользователь | 2024-01-25 18:00:00 | 2024-04-30 12:30:00 |
5 | user5_photo.jpg | user5 | pass5678 | user5@example.com | Администратор | 2024-02-28 09:15:00 | 2024-05-05 08:45:00 |
id | date | id_type | description |
---|---|---|---|
1 | 2023-10-10 15:30:00 | 1 | Initial event description |
2 | 2023-11-05 09:00:00 | 2 | Follow-up event |
3 | 2023-12-01 17:45:00 | 1 | Update event details |
4 | 2024-01-20 12:10:00 | 3 | Special event description |
5 | 2024-02-14 14:25:00 | 2 | Regular check |
id | name |
---|---|
1 | Event Type A |
2 | Event Type B |
3 | Event Type C |
4 | Event Type D |
5 | Event Type E |
id | id_user | id_anime | date | rate | text | id_reccomendation |
---|---|---|---|---|---|---|
1 | 101 | 201 | 2023-10-10 15:30:00 | 8.5 | Great storyline | 3 |
2 | 102 | 202 | 2023-11-11 16:45:00 | 9.0 | Excellent animation | 2 |
3 | 103 | 203 | 2023-12-12 18:00:00 | 7.5 | Good but slow-paced | 1 |
4 | 104 | 204 | 2024-01-13 20:30:00 | 8.0 | Strong character development | 5 |
5 | 105 | 205 | 2024-02-14 12:15:00 | 9.5 | Amazing action scenes | 4 |
id | recommendation |
---|---|
1 | Highly recommended |
2 | Worth watching |
3 | Good for anime fans |
4 | Suitable for all audiences |
5 | Only for genre enthusiasts |
Пусть пользователь зарегистрирован в приложении с электронной почтой = "user@mail.ru" и паролем = "123123123".
SELECT email, password
FROM USERS
WHERE email = "user@mail.ru" AND password = "123123123";
Количество запросов: 1. Количество задействованных таблиц: 1.
Пусть пользователь регистрируется в приложении с электронной почтой = "user2@mail.ru", логином = "login" и паролем = "Querty_0987765".
INSERT INTO USERS (email, login, password)
VALUES ("user2@mail.ru", "login", "Querty_0987765");
Количество запросов: 1. Количество задействованных таблиц: 1.
Пусть название аниме = "anime_name"
SELECT Anime.name, Anime.cover, Anime.episodes, Anime.date, Anime.rating, Anime.rates_count, Anime.description, Genres.name, Types_Anime.name, Age_Ratings.name, Other_Names.name, Studios.name, Reviews.date, Reviews.rate, Reviews,text, Reccomendations.reccomendation, User.photo, User.login FROM Anime
INNER JOIN Genres
ON Anime.id_genre = Genres.id
INNER JOIN Types_Anime
ON Anime.id_type = Types_Anime_id
INNER JOIN Age_Ratings
ON Anime.id_age_rating = Age_Ratings.id
INNER JOIN Other_Names
ON Anime.id_other_names = Other_Names.id_other_names
INNER JOIN Studios
ON Anime.id_studio = Studios.id
INNER JOIN Reviews
ON Anime.id_reviews = Reviews.id_anime
INNER JOIN Users
ON Reviews.id_user = User.id
INNER JOIN Reccomendations
ON Reviews.id_reccomendation = Reccomendations.reccomendation
WHERE name = "anime_name";
Количество запросов: 1. Количество задействованных таблиц: 9.
Пусть пользователь зарегистрирован с логином "Osaka1998".
SELECT photo, login, registred_at, updated_at, Reviews.text, Reviews.date, Anime.name, Anime.rating
FROM Users
INNER JOIN Reviews
ON Users.id = Reviews.id_user
INNER JOIN Anime
ON Reviews.id_anime = Anime.id
WHERE login = "Osaka1998";
Количество запросов: 1. Количество задействованных таблиц: 3.
Пусть пользователь зарегистрирован с логином "Osaka1998". Произведем замену этого логина на "Makaka_228".
UPDATE Users SET login = "Makaka_228", password = "key", photo = "url1"
WHERE login = "Osaka1998";
Количество запросов: 1. Количество задействованных таблиц: 1.
Пусть пользователь зарегистрирован с логином "Osaka1998".
SELECT login, Types_Update.name, Accounts_Logs.date, Accounts_Logs.description
FROM Users
INNER JOIN Accounts_Logs
ON Users.id = Accounts_Logs.id_user
INNER JOIN Types_Update
ON Accounts_Logs.id_type = Types_Update.id
WHERE login = "Osaka1998";
Количество запросов: 1. Количество задействованных таблиц: 3.
Пусть пользователь зарегистрирован с логином "Osaka1998".
SELECT Anime.name, Reviews.date, Reviews.rate, Reviews.text
FROM Users
INNER JOIN Reviews
ON Users.id = Reviews.id_user
INNER JOIN Anime
ON Reviews.id_anime = Anime.id
WHERE login = "Osaka1998";
Количество запросов: 1. Количество задействованных таблиц: 3.
SELECT Anime.name, Anime.cover, Anime.episodes, Anime.date, Anime.rating, Anime.rates_count, Anime.description, Genres.name, Types_Anime.name, Age_Ratings.name, Other_Names.name, Studios.name FROM Anime
INNER JOIN Genres
ON Anime.id_genre = Genres.id
INNER JOIN Types_Anime
ON Anime.id_type = Types_Anime_id
INNER JOIN Age_Ratings
ON Anime.id_age_rating = Age_Ratings.id
INNER JOIN Other_Names
ON Anime.id_other_names = Other_Names.id_other_names
INNER JOIN Studios
ON Anime.id_studio = Studios.id
INNER JOIN Reviews
ON Anime.id_reviews = Reviews.id_anime
GROUP BY Anime.id
ORDER BY COUNT(*) DESC
LIMIT 20;
Количество запросов: 1. Количество задействованных таблиц: 7.
SELECT Anime.name, Anime.cover, Anime.episodes, Anime.date, Anime.rating, Anime.rates_count, Anime.description, Genres.name, Types_Anime.name, Age_Ratings.name, Other_Names.name, Studios.name FROM Anime
INNER JOIN Genres
ON Anime.id_genre = Genres.id
INNER JOIN Types_Anime
ON Anime.id_type = Types_Anime_id
INNER JOIN Age_Ratings
ON Anime.id_age_rating = Age_Ratings.id
INNER JOIN Other_Names
ON Anime.id_other_names = Other_Names.id_other_names
INNER JOIN Studios
ON Anime.id_studio = Studios.id
INNER JOIN Reviews
ON Anime.id_reviews = Reviews.id_anime
GROUP BY Anime.id
ORDER BY COUNT(*) ASC
LIMIT 20;
Количество запросов: 1. Количество задействованных таблиц: 7.
SELECT Anime.name, Anime.cover, Anime.episodes, Anime.date, Anime.rating, Anime.rates_count, Anime.description, Genres.name, Types_Anime.name, Age_Ratings.name, Other_Names.name, Studios.name FROM Anime
INNER JOIN Genres
ON Anime.id_genre = Genres.id
INNER JOIN Types_Anime
ON Anime.id_type = Types_Anime_id
INNER JOIN Age_Ratings
ON Anime.id_age_rating = Age_Ratings.id
INNER JOIN Other_Names
ON Anime.id_other_names = Other_Names.id_other_names
INNER JOIN Studios
ON Anime.id_studio = Studios.id
INNER JOIN Reviews
ON Anime.id_reviews = Reviews.id_anime
GROUP BY Anime.id
HAVING AVG(Reviews.rate) >= 3 AND AVG(Reviews.rate) <= 7
ORDER BY COUNT(*) DESC
LIMIT 20;
Количество запросов: 1. Количество задействованных таблиц: 7.
UPDATE Anime
SET review_count = (
SELECT COUNT(*)
FROM Reviews
WHERE Reviews.id_anime = Anime.id
);
Количество запросов: 2. Количество задействованных таблиц: 2.
UPDATE Anime
SET rating = (
SELECT AVG(rating)
FROM Reviews
WHERE Reviews.id_anime = Anime.id
);
Количество запросов: 2. Количество задействованных таблиц: 2.
UPDATE Users
SET reviews_count = (
SELECT COUNT(*)
FROM Reviews
WHERE Reviews.id_user = Users.id
);
Количество запросов: 2. Количество задействованных таблиц: 2.
Основываясь на расчётах объемов информации в пункте "Оценка удельного объема информации" для нереляционных и реляционных БД, можно сделать следующее сравнение.
- Разница общих объемов нереляционной и реляционной БД соответственно:
V(U) = (19797 * U + 1210) - (23917428 * U + 3560540) = -2399761 * U - 3560330
- Разница чистых объемов нереляционной и реляционной БД соответственно:
V_clean(U) = (10757 * U + 1330) - (4088 * U + 240000) = 6669 * U - 238670
В реляционных БД данные занимают больше объема. Однако, при расчете "чистых" объемов реляционные БД оказываются более "легкими".
Количество запросов для совершения юзкейсов в зависимости от числа объектов в БД и прочих параметров:
Use case | Нереляционная модель | Реляционная модель |
---|---|---|
Авторизация | 1 | 1 |
Регистрация | 1 | 1 |
Выход из аккаунта | 1 | 1 |
Массовый импорт | U | U |
Массовый экспорт | 1 | 1 |
Поиск аниме | 1 | 1 |
Просмотр информации об аниме | 1 | 1 |
Выставление оценки произведению | 1 | 1 |
Комментирование произведения | 1 | 1 |
Редактирование комментария произведения | 1 | 1 |
Просмотр профиля | 1 | 1 |
Просмотр истории пользователя | 1 | 1 |
Изменение настроек | 1 | 1 |
Просмотр отзывов пользователя | 1 | 1 |
Просмотр статистики | 1 | 1 |
Поиск пользователя | 1 | 1 |
Количество задействованных коллекций в нереляционной модели равно трем(users, anime, review). В реляционной же БД это количество будет значительно больше, поскольку каждая подколлекция выражается в дополнительную сущность (Anime, Genres, Types_Anime, Age_Ratings, Other_Names, Studios, Status, Users, Account_Logs, Types_Update, Reviews, Reccomendations).
В ходе сравнения реляционных и нереляционных баз данных можно выделить несколько ключевых моментов.
-
Удельный объем информации: Реляционные БД демонстрируют больший общий объем, однако при рассмотрении "чистых" объемов, то есть объема информации без учета вспомогательной структуры, оказывается, что реляционные модели имеют меньший объем.
-
Запросы по отдельным юзкейсам: Нереляционная БД использует меньшее количество коллекций, что приводит к более простой модели данных и меньшему числу необходимых запросов. Также реляционная БД требует гораздо большего количества сущностей, что может усложнить процесс запросов и увеличивает траты ресурсов.
Таким образом, в данном проекте нереляционная модель данных подходит лучше поскольку выигрывает по простоте реализации, а также обеспечивают гибкость и простоту при работе с менее структурированными данными.