50

快速问题:

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

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

  • 徽章标识 (1)
  • 徽章标题(10K 徽章)
  • 徽章图片(10k.jpg)
  • 徽章标准([帖子] > = 10000)
    ...

Winded-问题:

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

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

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

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

有什么提示吗?

Stackoverflow 存档:


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

4

7 回答 7

23

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

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

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

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

我建议您阅读这些Daily WTF文章,了解为什么这种方法会导致疼痛。

于 2009-06-26T14:17:47.797 回答
22

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

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 字段。

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

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

于 2009-06-26T15:12:29.683 回答
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
于 2009-06-26T13:49:47.667 回答
5

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

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

于 2011-08-02T21:29:51.043 回答
3

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

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

于 2009-06-26T13:50:56.337 回答
3

我为简短而道歉。

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

badge_criteria
badge_key int
badge_criteria varchar(max)

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

于 2009-06-26T14:47:01.263 回答
2

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

更新:

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

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

于 2009-06-26T13:52:03.417 回答