“徽章”系统的数据库架构&任意标准(MySQL / PHP)

时间:2009-06-26 13:44:31

标签: database-design badge

晨间-问题:

总而言之,我对如何设计这样一个允许无限制徽章规则创建而不需要对数据库中以前存在的用户表进行结构更改的数据库感到困惑。

存储徽章标题,标准等。该表的外观如何?

  • badge_id(1)
  • badge_title(10K徽章)
  • badge_image(10k.jpg)
  • badge_criteria([posts]> = 10000)
    ...

啰嗦-问题:

我想在我自己的个人项目中实施徽章系统,但我正在寻求一些关于如何最好地做这样的事情的建议。我一直在阅读有关徽章系统的一些问题,但是没有看到数据库架构受到太多关注。

基于用户点的徽章(假设的“10k徽章”)看起来非常简单。任何影响用户声誉的事件(upvotes,downvotes,answer-accepted等)都会调用一种方法来审核用户的新声誉,并可能颁发徽章。

该系统听起来非常简单,但对于想要在未来几乎不费力地创建无数徽章的管理员而言,这看起来像是一个数据库 - 其中一些可能基于不同的标准,而不是只是用户的声誉。

用户信誉可能是用户记录本身的值。但理想情况下,您不希望在创建新徽章时不必在用户表中添加新字段吗?例如“Edited 100 Entries”徽章 - 您不会在用户表中创建新列“entries_edited”,不是吗?然后在每个条目编辑后递增...

任何提示?

Stackoverflow存档:


注意:我不是问如何将徽章与用户关联起来。我不是问如何授予徽章(将以编程方式完成)

7 个答案:

答案 0 :(得分:23)

鉴于徽章标准可能是任意复杂的,我认为您不能将其存储在分解为“简单”数据元素的数据库表中。试图编写一个可以处理任意复杂标准的“规则引擎”,这将会让你走上基本上重写编程语言中所有工具的道路。

如果您事先知道您希望徽章仅限于某些字段(即徽章仅基于声誉或编辑数量等),那么您可以将它们存储在如下的简单表格中:

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

或者,您可以使用某种DSL来编写“规则”,但最终还是必须创建一个解析器来解析规则,以及执行这些规则。根据您在DSL中所需的复杂程度,这可能不是一项简单的任务。这看起来就像你在问题中的路径,其中有一个Criteria列(可能是纯文本),其中包含“[Reputation]> 1000”或“[Posts]> 5”。您仍然需要解析并执行这些规则,编写某些内容的复杂性取决于您希望这些规则的复杂程度。

我建议你阅读these每日WTF articles,了解这种方法导致疼痛的原因。

答案 1 :(得分:19)

根据您想要使用它的程度,您的架构会变得相当复杂。在我看来,您需要跟踪的基本元素是:

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)。然后,您重新编译受所获得的点影响的徽章的点数,并使用point_earned更新user_badges表。然后根据徽章表中的required_points检查user_badges中的points_earned字段。

通过为不同的点类别指定不同的权重,甚至为特定徽章的点类别指定不同的权重,您可以获得更多的体验。但是这种设置允许在不改变表结构的情况下相当容易地创建和管理无限量的徽章和点类别。

如果这完全不是你想要的,那么我认为我应该至少得到一两次投票。

答案 2 :(得分:5)

您可以在一个表中跟踪您的唯一用户,在另一个表中跟踪唯一的徽章,然后创建一个交叉引用表来关联它们。

用户可以拥有许多徽章,徽章可以包含许多用户。

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

答案 3 :(得分:3)

我不会为编辑徽章创建增量。我认为你应该在后台运行一个工作,并计算(但是)编辑的帖子的编号,这些编辑对于没有编辑徽章的成员。当您看到计数超出所需范围时,您会在数据库中添加一个条目,告知用户具有徽章。

我认为其他徽章的情况大致相同。尝试限制写入次数,不要直接写入用户表中徽章信息的计数。使用包含徽章信息的表并将其链接到用户表。

答案 4 :(得分:3)

我为简短而道歉。

为了实现这样的系统,我可能会创建一个表,用于存储存储过程名称或实际查询,用于确定特定用户是否已获得徽章。

badge_criteria
badge_key int
badge_criteria varchar(max)

您可以提取并执行用户未从中间层获得的徽章查询,但您不必进行任何代码或结构更改即可添加新徽章。

答案 5 :(得分:3)

我正在接近它:创建一个表来存储所有徽章,并让一列引用一个函数来运行以查看徽章是否被授予。这样,表格仍然很简单,确定徽章的逻辑可以保存在最适合的代码中。

使用此方法,徽章要求也可以链接在一起,以形成更复杂的依赖关系。例如,用户必须在特定时间范围内收到三个单独的特定徽章才能获得此徽章。

答案 6 :(得分:2)

在数据库中几乎不可能做到这一点 - 授予徽章应该在应用程序中的业务逻辑中完成。这样,您就拥有了所需的所有现有数据(编辑,访问,声誉等),并且可以根据需要进行处理。

更新

如果按照标准,您的意思是确定是否以及如何授予徽章的规则,那么这不应该存储在数据库中。这几乎是不可能测试和维护的。

如果您的意思是,例如,存储“编辑数量”,则无法在需要时修改表或存储过程以包含该数据。