Проектирование базы данных для многопользовательской / одиночной викторины - PullRequest
0 голосов
/ 14 января 2019

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

Существует 2 типа пользователей, скажем, «Администратор» и «Рабочий», и у них разные роли.

Администратор может сделать CRUD вопросов, а также может создать комнату, в которую пользователи могут присоединиться, чтобы играть вместе (это просто имя, что-то вроде Kahoot!), Но, возможно, это хорошая идея для создания большего количества атрибутов внутри это как, ВОЗ играет в этой комнате, ТОЧКИ для всех, но давайте поговорим об этом позже, когда я покажу вам дизайн.

Хорошо, дело в том, что у меня есть дизайн:

Таблица User, которая содержит:

_id
username
password
date_creation

Это значение по умолчанию, но тогда мне интересно, как мне определить Роль, если это Администратор или Рабочий, что-то вроде isAdmin: true, а затем я проверяю этот Bool? Или я могу создать другую таблицу с именем Role и подключить ее к таблице User?

Но, возможно, мне нужно создать таблицу для обоих, я имею в виду администратора, у которого есть пароль, и некоторые функции, а затем пользователя Worker, у которого есть другой пароль и другие функции.

Тогда я бы хотел иметь таблицу Вопросов, в которой содержится:

_id
question_name
answers[1,2,3,4]
correctAnswer or answers because it can be multi option chooser
topic
isExamQuestion
dificulty

Тогда таблица комнаты должна содержать:

_id
name
capacity
type (game can be as a group or solo) that's why this attribute
exam (This should be a flag to know if this question is for an exam or not (It can be for EXAM or PRACTISE)
ranking (This is the top X from 1 to X)
don't think if I have to add the winner here because if I get the position 0 from ranking I get the winner...

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

_id
Name
Questions[...]
Then I have to store like a historic about what are the questions worker has answered correct and what did not, to make some statistics, but I need to store some historicals for Admin to see in this topic the average that Workers have failed more is : Question23 (for instance) something like that.

Чего мне не хватает, не могли бы вы помочь мне разобраться, как сделать этот дизайн лучше?

ПРИМЕЧАНИЕ. Я использую Spring для серверной части, Angular для Frontend и Android для App, хотя я могу изменить что-нибудь, чтобы работать с этой базой данных быстрее / лучше.

EDIT

Есть ход игры, если вам нужно больше деталей и если я неправильно объяснил.

Административный поток

  1. Создание вопросов (с различными типами ответов, такими как True / false, с пометками (одно и несколько ответов), текстом и т. Д ...)
  2. Создайте «игру», в которую могут присоединиться работники (в основном это программирование), но это должна быть комната с такими атрибутами, как идентификатор комнаты, maxNumber, тип (экзамен) и хранение историй, также есть тип игры (например, изображения, видео и т. д.)
  3. Посмотреть статистику о работниках. Это значит, увидеть, сколько ответов они ответили правильно, не получилось, посмотреть по теме (Это похоже на объединения и прочее, но дизайн должен быть хорошо сделан)
  4. См. Историю экзаменов, которые он делал раньше со всей информацией (участник, оценка, время, материал)

И рабочий поток

Он может попрактиковаться в том, что он отвечает на вопросы в случайном порядке или по темам (каждый отдельный ответ должен быть сохранен для статистики, чтобы избежать повторения ответов, которые он отвечает правильно), а также он может сдавать экзамены (не многопользовательские), просто опция, которую администратор может проверьте, является ли вопрос частью экзамена или нет.

А затем в комнате вещи, он может присоединиться с идентификатором.

Если вам нужны дополнительные разъяснения, дайте мне знать, и я отвечу вам как можно скорее.

Ответы [ 3 ]

0 голосов
/ 24 января 2019

У меня есть два замечания по поводу вашего дизайна:

Во-первых:

Вам нужна таблица Profile с one-to-many с таблицей User, таким образом, если вы хотите применить еще одну привилегию, просто добавьте новую запись профиля:

User таблица:

Id
Username
Fullname
Profile_id
...

Profile таблица:

Id
Name
Description

Второе:

Exam и Question равны many-to-many, чтобы разбить его, у вас будет третий стол Question_Exam:

Question_Exam

 id_exam
 Id_Question
 Answer(provided)
 Id_user(taking the exam)
 IsCorrect(boolean, to avoid farther queries )
 date

Topic и Question являются one-to-many

Question таблица:

 Id
 Name
 Answer(The correct one)
 Id_topic

Другая структура в порядке.

0 голосов
/ 24 января 2019

Честно говоря, если вы уверены, что вам понадобятся только возможные типы - как сейчас, так и в будущем - простой bool isAdmin в вашей пользовательской таблице будет хорошо работать. Все остальное, что делает админ, может быть обработано со стороны программирования. Нет необходимости засорять вашу базу данных.

Тем не менее, если есть небольшой шанс, что в будущем у вас появятся другие типы пользователей, ответ Максима - путь. Таким образом, добавить другую роль, например «Редактор», так же просто, как добавить запись в таблицу «Роль». На самом деле, добавить 1000 новых типов пользователей так же просто, как добавить записи в вашу таблицу «Роль». Поскольку у вас уже есть таблица, которую вы ищете для роли, вашему коду не нужно беспокоиться обо всех возможных типах пользователей (что является проблемой, если их много), а только о тех, которые ему нужны. БД обрабатывает все остальное.

Одним из недостатков ответа Максима является то, что для реализации в БД требуется больше работы и больше работы для просмотра / обновления роли пользователя.

Чтобы реализовать в БД, вам нужно создать целую дополнительную таблицу и убедиться, что она правильно связана. Это не сложно, но, особенно если вы новичок в dbs, это дополнительная работа, которая может вам не стоить. Это также означает, что со стороны обслуживания у вас есть еще одна таблица, на которой можно следить. Не большая сделка, но, опять же, о чем подумать.

Со стороны кода это также создает дополнительные хлопоты. С одной стороны, тип пользователя больше не находится непосредственно в вашей таблице пользователей - идентификатор есть. Это означает, что если вы хотите узнать имя типа пользователя, вам придется либо: а) запросить в базе данных этот тип пользователя на основе имеющегося у вас идентификатора, либо б) присоединиться к двум таблицам, что иногда может быть непросто. Обновление роли также имеет похожие задачи.

Опять же, это не огромные проблемы, просто вещи для размышления. Это может не стоить дополнительной работы, если у вас будет только два возможных варианта.

Итак, короче говоря, логическое значение будет работать и его легко реализовать, но оно не масштабируется. Ответ Максима вполне масштабируем и облегчает будущее расширение, но несколько сложнее в реализации и обслуживании. Вам придется принять решение, что вы предпочитаете.

0 голосов
/ 20 января 2019

На самом деле ваша система состоит из трех логических частей (модулей):

  • модуль пользователя, который содержит пользовательские данные и реализует аутентификацию и авторизацию действий пользователя
  • модуль вопросников, который включает управление вопросами и ответами
  • модуль истории анкет, содержащий историю каждого пользователя

Дизайн базы данных этих модулей может выглядеть следующим образом enter image description here

МОДУЛЬ ПОЛЬЗОВАТЕЛЯ:

role - содержит роли пользователя в системе

  • id - уникальный идентификатор роли
  • name - имя роли, например, admin, работник и т. Д.

пользователь - содержит пользователей и информацию о назначенных им ролях

  • id - уникальный идентификатор пользователя
  • имя пользователя
  • пароль
  • role_id - идентификатор роли, которая была назначена пользователю

МОДУЛЬ ВОПРОСНИКОВ:

тема - содержит темы вопроса

  • id - уникальный идентификатор темы
  • name - название темы

вопрос - содержит вопросы

  • id - уникальный идентификатор вопроса
  • topic_id - идентификатор темы вопроса
  • текст - содержание вопроса
  • is_exam_question - экзаменационный вопрос или нет
  • тип - тип ответов (логические, флажки и т. Д.)
  • Трудность

ответ - содержит все ответы на вопросы

  • id - уникальный идентификатор ответа
  • question_id - идентификатор вопроса, содержащего ответ
  • текст - содержание вопроса
  • is_correct - флаг, означающий, что ответ является истинным или ложным

номер - содержит информацию о номерах

  • id - уникальный идентификатор рома
  • имя - название рома
  • вместимость - максимальное количество работников, которые могут присоединиться к комнате
  • тип - тип комнаты: группа, соло или др.
  • learing_type - тип комнаты: экзамен, практика или др.

user_in_room - содержит информацию о пользователях, которые присоединились к комнате

  • user_id - идентификатор пользователя, который присоединился к комнате
  • room_id - идентификатор комнаты
  • оценка - текущая оценка пользователя в комнате

ИСТОРИЧЕСКИЙ МОДУЛЬ:

user_question_history - содержит информацию о вопросах, на которые ответил пользователь

  • user_id - идентификатор пользователя
  • room_id - идентификатор комнаты, где пользователь ответил на вопросы
  • question_id - идентификатор вопроса, на который ответил пользователь
  • оценка - оценка пользователя по вопросу

user_answer_history - содержит информацию об ответах, выбранных пользователем

  • user_id - идентификатор пользователя
  • room_id - идентификатор комнаты, где пользователь ответил на вопросы
  • question_id - идентификатор вопроса, на который ответил пользователь
  • answer_id - идентификатор ответа, который был выбран пользователем

Использование этой схемы дает возможность создавать различные отчеты. Например, вы можете отобразить результат всех пользователей по комнате

SELECT r.id,
    r.name,
    u.username,
    ur.score
FROM room as r
LEFT JOIN user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user as u ON u.id = ur.user_id
WHERE r.id = <id>

Или вы можете посмотреть подробную информацию об ответах пользователя

SELECT 
    q.text,
    a.text
FROM user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user_question_history as uqh ON ugh.user_id = ur.user_id AND ugh.root_id = ur.room_id
LEFT JOIN question as q ON q.id = ugh.question_id
LEFT JOIN user_answer_history as uah ON uah.user_id = ugh.user_id AND uah.room_id = ugh.room_id AND uah.question_id = ugh.question_id
LEFT JOIN answer as a ON a.id = uah.answer_id
WHERE ur.room_id = <id> AND ur.user_id = <id>
...