Дизайн базы данных: профили пользователей, как на Meetup.com - PullRequest
7 голосов
/ 03 ноября 2011

В Meetup.com, когда вы присоединяетесь к группе встреч, вам обычно требуется заполнить профиль для этой конкретной группы. Например, если вы присоединяетесь к группе встреч с фильмами, вам может потребоваться указать жанры фильмов, которые вам нравятся, и т. Д.

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

  1. Пользователи могут создавать свои собственные группы и определять, какие детали запрашивать у пользователей, которые присоединяются к этой группе (поэтому, что-то немного динамичное - возможно, предполагается, что по крайней мере требуется дизайн EAV)
  2. Разработчик теперь решает, какие группы создавать, и указывает, какие данные следует запрашивать у пользователей, которые присоединяются к этой группе (это означает, что данные профиля будут предварительно определены и «жестко запрограммированы» в системе)

Как лучше всего моделировать такие данные?

Более сложный пример:

Группа "Кинозрители" просит своих членов указать следующее:

  • Имя
  • Дата рождения (для расчета возраста участника)
  • Пол (необходимо выбрать из "мужской" или "женский")
  • Любимые жанры (необходимо выбрать 1 или более из списка указанных жанров)

Группа "Экстремальные виды спорта" просит своего участника указать следующее:

  • Имя
  • Описание понравившихся занятий (повествовательная форма)
  • Почтовый индекс

Суть в том, что каждая группа может требовать разные данные от членов, присоединяющихся к их группе. В идеале я хотел бы, чтобы кто-нибудь создал группу (аля MeetUp.com). Тем не менее, мне также нужна возможность довольно хорошо запрашивать участников (например, найти всех женщин, которые ходят в кино в возрасте от 25 до 30 лет).

Ответы [ 7 ]

7 голосов
/ 15 ноября 2011

Для чего-то подобного ... вам нужна максимальная нормализация, чтобы у вас не было нигде дублирующих данных. Поскольку ваши пользовательские таблицы могут содержать записи одного и того же типа, я думаю, что для этого вам может потребоваться значение 3NF .

Мое предложение будет таким: взорвите свои таблицы, чтобы у вас было что-то близкое к 6NF с EAV, чтобы каждый вопрос, на который должны ответить пользователи, имел свою собственную таблицу. Затем все созданные вами таблицы будут ссылаться на одну из ваших таблиц вопросов. Это позволяет избежать дублирования вопроса данных. (Например, вам не нужна запись в группе «MovieGoers» с именем «Джон Браун» и запись в группе «Экстремальные виды спорта» с именем «Джонни Б.» для того же пользователя; не хочу, чтобы его ответ «какой ваш любимый цвет» был «синим» в одной группе и «красным» в другой. Любые данные, которые могут охватывать группы, например общие вопросы, будут нормализованы в этой форме.)

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

Обратите внимание, что вы, вероятно, могли бы избежать использования только общих полей, если бы вы действительно этого хотели. Примеры общих полей: имя, местоположение, пол и другие; Вы также можете сделать то же самое для общих вопросов, таких как «какой ваш любимый цвет» или «у вас есть домашние животные» или что-то в этом роде. Вопросы группы, которые не охватывают группы, могут быть сохранены в отдельной таблице для этой группы без разбора. Я бы не советовал, потому что он не был бы таким же гибким, как вариант с чистой 6NF, и вы рискуете дублировать (как вы заранее определяете, какие вопросы не будут общими вопросами?), Но если бы вы действительно этого хотели, вы могли бы сделай это.

Здесь есть хороший вопрос о 6NF: Хотелось бы понять 6NF с примером

Я надеюсь, что это имело смысл, и я надеюсь, что это помогает. Если у вас есть какие-либо вопросы, оставьте комментарий.

6 голосов
/ 18 ноября 2011

Действительно, это именно та проблема, для которой SQL не является правильным решением. Забудь о нормализации. Это именно то, что нужно для хранилищ документов NoSQL. Каждый пользователь в качестве документа, имеет некоторые необходимые поля, такие как id, name, pwd и т. Д. И каждая группа добавляет возможность добавлять некоторые поля. Уникальные поля могут иметь имена с префиксом group-id, общие поля (которые понимают более общую концепцию) могут иметь это имя поля свободным.

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

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

1 голос
/ 16 ноября 2011

Прежде всего, я хотел бы отметить, что следующая структура является лишь основой для вашей БД, и вам нужно будет расширить / уменьшить ее.

В БД есть следующие сущности:

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

«Моделирование»:

**User**
user_id
user_name

**Group**
name
group_id

user_group
user_id (FK)
group_id (FK)

**requirement**:
requirement_id
requirement_name
requirement_type (FK) (means the type: combo, free string, date) - should refers to dictionary)

**template**
template_id
template_name

**template_requirement**
r_id (FK)
t_id (FK)

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

**restrictions**
group_id
template_id
requirement_id (should be here as template_id because the same requirement can exists in different templates and any group can consists of many templates)
restriction_type (FK) (points to another dict: value, length, regexp, at_least_one_value_choosed and so on)

Итак, как я уже сказал, это основа.Вы можете смело упростить эту схему (уничтожить таблицы, несколько шаблонов для группы).Или вы можете сделать его более общим, добавив возможность создавать и публиковать temaplate, требования и т. Д.

Надеюсь, вы найдете эту идею полезной

0 голосов
/ 18 ноября 2011

Если вы не привязаны к mysql, я предлагаю вам использовать postgresql, который предоставляет встроенный массив типов данных.

вы можете определить массив массива поля varchar для хранения групповых полей в таблице групп. для хранения значений вы можете сделать то же самое в таблице членства.

По сравнению с xml-типами, основанными на разборе строк, этот подход к массиву будет очень быстрым.

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

0 голосов
/ 18 ноября 2011

У меня были похожие проблемы с этим. Я не уверен, что это будет лучшая рекомендация для вашей конкретной ситуации, но учтите это.

  1. Предоставляют средства хранения данных в виде XML, JSON или другого формата, который разделяет данные, но в основном сохраняет их в поле, которое не имеет определенного формата.

  2. Предоставить способ хранения определения этих данных

  3. Обеспечение таблицы поиска / индексации для данных.

Это комбинация техник, указанных уже.

По сути, вы должны создать некоторый интерфейс для ваших клиентов, чтобы создать «форму» для того, что они хотят сохранить. Эта форма будет указывать, какие части информации они хотят от пользователя. Также будет указано, какие части информации вы хотите искать.

Сохранить эту информацию в таблице определения.

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

После ввода пользовательских данных сохраните данные (в формате xml или чего-либо еще) в одну таблицу с уникальным идентификатором. В то же время другая таблица будет заполнена как индекс с

идентификатор, где были сохранены данные XML имя поля данных хранится в Значение данных поля сохраняется. идентификатор определения данных.

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

Эти данные должны преобразовываться после их получения.

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

0 голосов
/ 14 ноября 2011

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

users
user_id, user_name, password, birth_date, gender

1, Robert Jones, *****, 2011-11-11, M

group
group_id, group_name

1, Movie Goers
2, Extreme Sports

group_membership
user_id, group_id
1, 1
1, 2

group_data
group_data_id, group_id, group_data_name

1, 1, Favorite Genres
2, 2, Favorite Activities

group_data_value
id, group_data_id, group_data_value
1,1,Comedy
2,1,Sci-Fi
3,1,Documentaries
4,2,Extreme Cage Fighting
5,2,Naked Extreme Bike Riding

user_group_data
user_id, group_id, group_data_id, group_data_value_id

1,1,1,1
1,1,1,2
1,2,2,4
1,2,2,5
0 голосов
/ 03 ноября 2011

Вы можете сохранить такие данные как JSON или XML (Структура, Данные)

Таблица пользователей

  • ИД пользователя
  • Имя пользователя
  • Пароль
  • Группы -> Массив JSON всех групп

Таблица групповой структуры

  • Groupid
  • Имя группы
  • Структура группы -> Структура JSON (с указанными полями)

Таблица данных группы

  • ИД пользователя
  • Groupid
  • Groupdata -> Данные JSON
...