成就/徽章系统

Posted

技术标签:

【中文标题】成就/徽章系统【英文标题】:Achievements / Badges system 【发布时间】:2010-12-17 05:10:18 【问题描述】:

我一直在浏览这个网站寻找答案,但我仍然有点不确定如何在其数据库结构和实施中规划一个类似的系统。

phpmysql 中,很明显会立即获得一些成就(当采取专门的操作时,在 SO 情况下:填写所有个人资料字段),尽管我知道 SO 会在一段时间后更新并分配徽章.拥有如此多的用户和徽章不会造成性能问题(就规模而言:用户和徽章的数量都很高)。

所以我假设的数据库结构很简单:

Badges     |    Badges_User      |    User
----------------------------------------------
bd_id      |    bd_id            |  user_id
bd_name    |    user_id          |  etc
bd_desc    |    assigned(bool)   |  
           |    assigned_at      |

但正如一些人所说,最好采用增量样式方法,这样拥有 1,000,000 个论坛帖子的用户就不会减慢任何功能。

然后它会是另一个徽章表,可以是增量的,还是只是上面 badges_user 表中的“进度”字段?

感谢阅读,请关注所需系统的可扩展性(例如数千名用户和 20 到 40 个徽章)。

编辑:为了消除我之前将_at 指定为日期/时间的一些困惑,授予徽章的标准最好放在为每个徽章准备好的查询/函数中,不是吗? (更好的灵活性)

【问题讨论】:

一些更受欢迎的徽章是否也比其他徽章检查得更多? 你能澄清一下“assigned(bool)”的必要性吗?除非您被分配了徽章,否则在第一种情况下您不会有映射,这不是多余的吗?为什么论坛帖子的数量很重要? 我的第一个错误!假设您根据发布的帖子数量分配徽章,即用良好的徽章奖励高帖子 -> 激励用户互动 @Fredrik,同意“assigned”,但“assigned_at”意味着您可以跟踪提到的 1,000,000 个论坛帖子徽章之类的内容。他基本上是在一张桌子上跟踪两种徽章。 没错,那肯定是个坏主意,不是吗? 【参考方案1】:

我会保持与你所拥有的类似的类型结构

Badges(badge_id, badge_name, badge_desc)
Users(user_id, etc)
UserBadges(badge_id, user_id, date_awarded)

然后根据您要跟踪的内容和@什么详细级别添加跟踪表...然后您可以相应地更新表并在其上设置触发器以“授予”徽章

User_Activity(user_id, posts, upvotes, downvotes, etc...)

您也可以从另一个方向跟踪统计数据并触发徽章奖励

Posts(post_id, user_id, upvotes, downvotes, etc...)


其他一些优点here

【讨论】:

【参考方案2】:

我认为您建议的结构(没有根据 cmets 的“已分配”字段)可以工作,添加一个附加表,例如“Submissions_User”,其中包含对 user_id 的引用和一个用于计数的递增字段提交。那么你所需要的只是一个this post 的“事件监听器”,我认为你已经准备好了。

编辑:对于成就徽章,在每次提交时运行事件侦听器(当然仅适用于提交的用户),并当场授予任何相关徽章。对于基于时间的徽章,我每晚都会运行 CRON 作业。遍历完整的用户列表一次,并根据需要奖励徽章。

【讨论】:

好的,这是最好的方法,在实施方面呢,就像我的问题一样,在设定的时间后奖励徽章,所以每隔几个小时,然后是 [foreach(badge)] - > 做所有用户或 [foreach(user)] - > 做所有徽章,这有什么不同吗?然后我可以设置不太可能在较长时间间隔内获得的徽章?想法..我会接受作为答案【参考方案3】:

我认为这是适合您的多对多表 (Badges_User) 的情况之一。 但稍作改动,就不会存储未分配的徽章。 我假设 assigned_at 是日期和/或时间。 默认是用户没有徽章。

Badges     |    Badges_User      |  User
----------------------------------------------
bd_id      |    bd_id            |  user_id
bd_name    |    user_id          |  etc
bd_desc    |    assigned_at      |  
           |                     |

这种方式只存储实际授予的徽章。 仅当用户获​​得徽章时才会创建 Badges_User 行。

问候 西格斯特

【讨论】:

【参考方案4】:

关于您包含的草图:去掉 badges_user 上的布尔列。那里没有任何意义:这种关系是根据谓词“用户 user_id 在assigned_at 获得徽章 bd_id”来定义的。

至于您的整体问题:首先将架构定义为关系型而不考虑速度(这将使您摆脱一半潜在的性能问题,可能以换取不同的性能问题),正确索引它(什么是正确取决于查询模式),然后如果它很慢,则从更快的那个中派生一个(仍然是关系的)设计。比如你可能需要预先计算一些聚合等。

【讨论】:

以上是关于成就/徽章系统的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 nosql 构建成就和徽章

如何在对系统的影响最小的情况下为您的 APP 处理成就/徽章/奖励?

Google Play 商店中未显示排行榜和成就徽章

Google Play 商店:我的应用页面不显示排行榜和成就图标/徽章

Rails“徽章”类型插件/教程?

编码成就系统的最佳方式