Архитектура базы данных для системы «значков» и произвольных критериев (MySQL/PHP)

StackOverflow https://stackoverflow.com/questions/1049233

  •  20-08-2019
  •  | 
  •  

Вопрос

Быстрый вопрос:

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

Сохранение названия бейджа, критериев и т. д.Как будет выглядеть эта таблица?

  • идентификатор_значка (1)
  • Badge_title (значок 10 тыс.)
  • бейдж_изображение (10k.jpg)
  • Badge_criteria ([сообщений] >= 10000)
    ...

Обмотанный-Вопрос:

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

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

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

Репутация пользователя, скорее всего, является значением внутри самой записи пользователя.Но в идеале не хотелось бы избежать необходимости добавлять новые поля в таблицу пользователей при создании новых значков?Например, значок «Отредактировано 100 записей» — вы бы не создали новый столбец «entries_edited» в таблице «Пользователи», не так ли?А затем увеличивайте это значение после каждой отредактированной записи...

Есть какие-нибудь подсказки?

Архив Stackoverflow:


Примечание:Я НЕ спрашиваю, как ассоциировать значки с пользователями.Я НЕ спрашиваю, как вручать значки (это будет сделано программно)

Это было полезно?

Решение

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

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

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

В качестве альтернативы вы можете использовать какой-то DSL для написания своих «правил», но в конечном итоге вам придется также создать синтаксический анализатор для анализа правил, когда вы их читаете, а также что-то для выполнения этих правил.В зависимости от сложности вашего DSL, это может оказаться нетривиальной задачей.Это похоже на путь, по которому вы идете в своем вопросе, с наличием столбца «Критерии» (предположительно обычного текста), в котором есть что-то вроде «[Репутация]> 1000» или «[Сообщения]> 5».Вам все равно придется анализировать и выполнять эти правила, а сложность написания чего-либо для этого зависит от того, насколько сложными вы хотите, чтобы эти правила были.

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

Другие советы

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

Badges awarded
Points earned

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

Point categories
Badge categories

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

badges:
badge_id
badge_name
required_points
....

point_categories:
point_id
category_name
weighting (optional)
...

point_groups:
badge_id
point_id
weighting (optional)
...

user_points:
user_id
point_id
points
...

user_badges:
user_id
badge_id
points_earned
badge_awarded (yes/no)
...

Ваш «административный» интерфейс позволит кому-то создать новый значок и выбрать, какие категории баллов необходимы для получения этого значка (point_groups).Всякий раз, когда пользователь зарабатывает баллы (user_points), вы обновляете таблицу user_points, а затем определяете, каким значкам эти баллы могут способствовать (point_groups).Затем вы перекомпилируете баллы для значков, на которые повлияли заработанные баллы, и обновите таблицу user_badges, указав значение point_earned.Затем проверьте поле Points_earned в user_badges на соответствие требуемым_очкам в таблице бейджей.

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

Если это совершенно не то, что вы ищете, то я думаю, что мне следует хотя бы получить один или два голоса за то, что я много пишу.

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

У пользователя может быть много значков, а у значка может быть много пользователей.

create table users (
id int,
name varchar
)

create table badges (
id int,
badge_name varchar
)


create table user_badges_xref (
user_id int,
badge_id int
)

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

Я не спрашиваю, как вручать значки.Я спрашиваю, как хранить критерии в базе данных.

Итак, вы хотите сохранить логическую операцию, необходимую для определения того, получен ли значок где-нибудь в поле?

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

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

Итак, в вашем поле критериев будет что-то вроде:

select "Badge Earned"
from all_posts 
where user_id = @user_id
having count(*) > 10000

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

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

Прошу прощения за краткость.

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

badge_criteria
badge_key int
badge_criteria varchar(max)

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

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

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

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

Обновлять:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top