【问题标题】:Database Architecture for "Badge" System & Arbitrary Criteria (MySQL/PHP)“徽章”系统和任意标准的数据库架构 (MySQL/PHP)
【发布时间】:2009-06-26 13:44:31
【问题描述】:

快速提问:

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

存储徽章标题、标准等。该表会是什么样子?

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

啰嗦的问题:

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

基于用户积分的徽章(假设的“10k 徽章”)看起来非常简单。任何影响用户声誉的事件(赞成、反对、接受答案等)都会调用一种方法来审查用户的新声誉,并可能授予徽章。

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

用户声誉可能是用户记录本身的一个值。但理想情况下,您不想在创建新徽章时避免向用户表添加新字段吗?例如“已编辑的 100 个条目”徽章 - 您不会在用户表中创建新列“条目编辑”,对吗?然后在每个条目编辑后增加它...

有什么提示吗?

Stackoverflow 存档:


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

【问题讨论】:

  • +1,因为我正在寻找相同的答案。
  • @Jonathan Sampson 您能否分享您自己的最后一个答案:1)您得出的结论是什么方法? 2) 从你的方法中吸取的教训。问候和感谢这个奇妙的问题。
  • Sampson 我也很好奇你是否完成了你的项目并且有什么有用的东西可以分享?我找到了你的帖子,因为我有同样的想法,将徽章的标准存储在徽章表中。我仍在研究实现我的系统的最佳方法,我很想听听任何做过的人的意见!谢谢
  • @JasonDavis 我没有。如果我今天要这样做,我可能会有一系列脚本(每个脚本代表一个徽章/成就),它们会定期运行。在我看来,一系列外部脚本是最灵活的解决方案,因为它允许超精细的临时条件。

标签: database-design badge


【解决方案1】:

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

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

【讨论】:

  • 存储逻辑以计算在代码中而不是在数据库中授予的徽章是个好主意
  • 哇,这就是创意!
【解决方案2】:

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

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 表。然后将 user_badges 中的 points_earned 字段与 badges 表中的 required_points 进行对比。

您可以通过为不同的点数类别分配不同的权重,甚至为特定徽章的点数类别分配不同的权重,从而变得更加精美。但是这种设置将允许在不更改表格结构的情况下相当轻松地创建和管理无限数量的徽章和积分类别。

如果这完全不是您想要的,那么我认为我至少应该为大量打字获得一两票。

【讨论】:

  • 赞成大量打字。另外,我认为这是正确的下坡路......但你在这条路上走多远取决于你。
  • 嗨,你能写下简单的查询来测试上表吗?
  • 我不明白为什么这个答案不是被接受和最受支持的答案。几个小时以来,我一直在思考其他人看到的我看不到的东西。对我来说,这是最好的逻辑,但很多大师绝对比我更了解:-(
  • +1 这是最好的答案。这是经过深思熟虑和彻底解释的。
  • 这适用于简单的情况,即徽章严格基于达到 OP 在问题中明确指出的一些点数。真正的问题是,您如何处理“无数”数量的徽章,而不仅仅是简单的“用户拥有 > X 点”类型的徽章。
【解决方案3】:

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

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

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

或者,您可以使用某种 DSL 来编写您的“规则”,但最终还必须创建一个解析器来在您读取规则时解析它们以及执行这些规则的东西。根据您希望 DSL 的复杂性,这可能不是一项简单的任务。这看起来像您在问题中要走的路径,其中有一个标准列(可能是纯文本),其中包含“[Reputation] > 1000”或“[Posts] > 5”之类的内容。您仍然需要解析和执行这些规则,而为此编写内容的复杂性取决于您希望这些规则有多复杂。

我建议您阅读 these Daily WTF articles 了解为什么这种方法会导致疼痛。

【讨论】:

  • 谢谢。你似乎是第一个真正理解我的问题的人;)
【解决方案4】:

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

一个用户可以有很多徽章,一个徽章可以有很多用户。

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

【讨论】:

  • 我不是在问如何将徽章与用户相关联 - 我是在问如何在未来创建和存储徽章的标准。
  • 我不是在问如何奖励徽章。我在问如何在数据库中存储标准。
【解决方案5】:

我不会为编辑徽章创建增量。我认为您应该在后台运行一项工作并计算()为尚未获得编辑徽章的成员编辑的帖子数量。当您看到计数超出您想要的范围时,您在数据库中添加一个条目,告诉用户拥有徽章。

我认为其他徽章也差不多。尽量限制写入次数,不要直接写入用户表中徽章信息的计数。使用包含徽章信息的表并将其链接到用户表。

【讨论】:

    【解决方案6】:

    我为简短而道歉。

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

    badge_criteria
    badge_key int
    badge_criteria varchar(max)
    

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

    【讨论】:

      【解决方案7】:

      这在数据库中几乎是不可能做到的——授予徽章应该在应用程序内的业务逻辑中完成。这样,您就拥有了所需的所有现有数据(编辑、访问、声誉等),并且可以按照您认为合适的方式进行处理。

      更新:

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

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

      【讨论】:

      • 我用代码授予徽章,是的。但如果我没记错的话,理想情况下徽章的标准将存储在数据库中。
      • 所以徽章标准应该存储在配置文件中?或者是什么?我要避免的事情是必须输入添加新徽章的实际逻辑。
      • 我从没想过配置文件,但这可以工作。我更多地考虑将常量存储在“Badge”类中——这本质上是一回事。这实际上取决于您使用的 PHP 框架。
      • 我现在正在尝试做一个徽章系统,我的一个想法是可能在我的徽章表中存储一个类方法来处理该徽章的逻辑,对他有什么想法吗?
      猜你喜欢
      • 1970-01-01
      • 2010-12-17
      • 2015-06-16
      • 2011-04-29
      • 2012-12-05
      • 1970-01-01
      • 2011-01-03
      • 2012-02-24
      • 2012-09-02
      相关资源
      最近更新 更多