Хранение данных динамической формы в СУБД, поиск оптимального подхода - PullRequest
1 голос
/ 01 декабря 2009

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

Краткое описание: каждый «документ» содержит различное количество вопросов (хотя и постоянное количество для каждого типа документа) и соответствующие ответы.

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

  +---------------+ 1      n +-----------+
  | DocumentType  |----------| Questions |
  +---------------+ Has many +-----------+
         |1                      1|
         |n Is of type           n| Belongs to
  +---------------+ 1      n +-----------+
  | DocumentEntry |----------|  Answers  |
  +---------------+ Has many +-----------+

Недостатком здесь является то, что запросы при извлечении документов, имеющих вопрос A с ответом B, становятся довольно сложными и, вероятно, довольно медленными, когда база данных увеличивается, что быстро будет.

Мне интересно, не наткнулся ли я на оптимальный подход к хранению данных или есть какое-то изящное решение, которое я мог бы пропустить.

1 Ответ

2 голосов
/ 01 декабря 2009

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

  • У вас есть document (или вопросник ), который содержит несколько questions. Оба они достаточно универсальны и требуют своих собственных таблиц, как вы это уже сделали.
  • Каждый вопрос имеет type, который определяет, какой это тип вопроса ( множественный выбор, произвольная форма, выбор одного ... ), и, конечно, вопрос также имеет options. Так что это еще две таблицы. Причиной здесь является то, что разделение их с реальным вопросом позволяет обеспечить определенный уровень абстракции, и ваши запросы все равно будут несколько простыми, хотя, возможно, и неоправданными.

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

Document
    bigint id
DocumentQuestions
    bigint document_id
    bigint question_id
Question
    bigint id
    varchar question
QuestionType
    bigint question_id
    bigint type_id
Type [pre-filled table with id:type pairs, such as 1=freeform, 2=select one etc.]
QuestionOptions
    bigint id
    bigint question_id
    varchar description
    varchar value

Answers
    bigint id
    bigint document_id
    [etc. such as user_id]
QuestionAnswers
    bigint answer_id
    bigint question_id
    bigint questionoptions_id

Такая конструкция допускает несколько вещей:

  • Сами вопросы можно использовать многократно, что очень удобно, если вы создаете общий текст " ответьте на эти x случайные вопросы из пула из y вопросов ".
  • Новые типы можно легко добавлять, не нарушая существующие.
  • Вы всегда можете довольно легко перемещаться по структуре, например: " Как назывался документ для этого ответа на один вопрос, который у меня есть? " или "сколько людей ответили неправильно на этот один вопрос ? "
  • Поскольку типы разделены, вы можете создать (веб) пользовательский интерфейс, который легко отображает состояние в базе данных - еще лучше, если при изменении типа вам, возможно, даже не придется прикасаться к коду вашего интерфейса.
  • Поскольку каждый возможный вариант вопроса - это отдельная строка в таблице QuestionOptions, вы можете очень легко получить фактическое значение.

Очевидная проблема с этим заключается в том, что для обеспечения целостности требуется довольно строгое соединение между таблицами, и при запуске будет проблематично работать. Кроме того, поскольку value в QuestionOptions - это varchar, вам нужно иметь возможность много разбирать материал, и вы можете даже ввести другое поле для подсказок по конверсии.

Надеюсь, это поможет, даже если вы не согласитесь с моим решением вообще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...