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

Это также можно сделать через графический интерфейс SSMS. Хорошая особенность этого метода в том, что он предупреждает вас о наличии каких-либо связей в этом столбце, а также может автоматически их удалять.

  1. Поместить таблицу в режиме конструктора (щелкните правой кнопкой мыши по таблице) следующим образом:

enter image description here

  1. Щелкните правой кнопкой мыши по столбцу в представлении «Дизайн» таблицы и выберите «Удалить столбец»

enter image description here

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

47
задан Community 23 May 2017 в 12:00
поделиться

6 ответов

Given that the badge criteria can be arbitrarily complex, I don't think you can store it in a database table broken down into "simple" data elements. Trying to write a "rules engine" that can handle arbitrarily complex criteria is going to take you down the path of basically re-writing all the tools that you have in your programming language.

If you know in advance you want the badges limited to only certain fields (i.e. badges are only based off reputation or number of edits or something), then you can store those in a simple table like:

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

Alternatively, you could use some kind of DSL to write your "rules" but you end up having to also create a parser to parse the rules when you read them as well as something to execute these rules. Depending on the complexity you want in your DSL, this may not be a trivial task. This looks like the path you are going in your question with having a Criteria column (presumably plain text) that has something like "[Reputation] > 1000" or "[Posts] > 5" in it. You still have to parse and execute those rules and the complexity of writing something to do so is dependent on how complex you want those rules to be.

I would recommend you read these Daily WTF articles for information on why this approach leads to pain.

23
ответ дан 26 November 2019 в 19:52
поделиться

You'd track your unique users in one table and unique badges in another then create a cross reference table to relate them.

A user can have many badges and a badge can have many users.

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
)

Statistics that might affect whether a user earns a badge are tracked as a part of the administration of the site. so something like an answer being accepted would be in a schema that relates questions & answers. in order to display the answer and the owner of the answer, there would be a relationship to the user table and triggers that would check for badge conditions whenever a change was made.

I'm not asking how to award badges. I'm asking how to store criteria within the database.

So you want to store the logical operation required to determine if a badge is earned in a field somewhere?

I think agree with the other poster that criteria should be a part of the business logic. That logic can be on the app side or within a trigger. I think that's a matter of style.

If you were really married to the idea of storing the criteria in a field, I'd store it as parameterized SQL and run it dynamically.

So this sort of thing would be in your criteria field:

select "Badge Earned"
from all_posts 
where user_id = @user_id
having count(*) > 10000
5
ответ дан 26 November 2019 в 19:52
поделиться

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

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

3
ответ дан 26 November 2019 в 19:52
поделиться

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

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

badge_criteria
badge_key int
badge_criteria varchar(max)

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

3
ответ дан 26 November 2019 в 19:52
поделиться

This is going to be next to impossible to do in the database - awarding badges should be done in your business logic within the application. That way, you have all the existing data you need (edits, visits, reputation, etc.) and it can be dealt with as you see fit.

Update:

If by criteria you mean rules that determine if and how the badge is awarded, then that is not something that should be stored in the database. This would be almost impossible to test and maintain.

If you mean, for example, storing the "number of edits", there's no way getting around modifying a table or stored procedure to include that data if you need it.

2
ответ дан 26 November 2019 в 19:52
поделиться

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

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 с required_points в таблице значков.

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

19
ответ дан 26 November 2019 в 19:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: