【问题标题】:How to implement one time (per user) messages in a web app?如何在 Web 应用程序中实现一次(每个用户)消息?
【发布时间】:2010-11-07 12:08:25
【问题描述】:

如果您想提醒用户某事(关于新功能、即将举行的活动、特别优惠等的一次性笔记),最好的方法是什么?

我主要关心数据表示,但如果还有更多需要考虑的问题,请指出。这是我第一次处理这个特殊问题。

到目前为止我的想法......

您可以有一个用户、一条消息和一个已查看/已确认消息表。当用户确认消息时,我们在 seen 表中有一个新条目,其中包含用户 ID 和消息 ID 对。

但是,seen 表会随着用户和消息数量的增加而迅速增长。在某些时候,这会变得笨拙(任何洞察力何时适用于单个服务器上的单个 mysql 数据库?)。

最好只为每条消息创建 1 个可见的表,然后以 20-30 个这样的额外表开始?真的不是问题。它只是带来了每次有新消息时都必须创建一个新表的额外麻烦(当然,这将在代码中自动执行 - 仍然需要更多编码)。

这是一个拥有 2-3K 当前用户的项目,但希望在明年将其增长到 10K,当然,我们也在考虑超越这一点......

编辑: 我对目前投票最多的方法一点也不感兴趣。 该提议似乎是预填充消息表并删除看到的消息。这似乎是更多的工作。每次添加新消息时,您不仅需要添加整个用户列表。每次添加新用户时,您还必须为新用户添加所有消息 - 单独的逻辑。

除此之外,消息被“看到”的记录实际上是没有记录。这似乎不对。另外,如果您以后决定使用简单的时间戳来跟踪何时看到消息。您必须重写大量代码,而其他代码变得无法使用。

最后,有人能告诉我为什么将新表添加到数据库中是如此可怕吗?添加新功能时,这不是一直发生吗?以任何 CMS 为例:Joomla 或 Wordpress。添加新插件时,您正在动态创建表。因此,它必须比“不这样做”更加细致入微和上下文。有哪些陷阱,在哪些情况下不做或可以做?

我知道您可能会说:在生产服务器上创建新表时要小心。确保它已经过很好的测试,但最终你只是添加了一个空表。

这可能需要和扩展答案,所以如果有人知道任何文章,请发布它们。

编辑: Gabriel Sosa 给出了他的消息表的一个很好的刷新示例,我将简单地创建一个类似于我最初发布的可见表,尽管也带有时间戳列。谢谢!

【问题讨论】:

    标签: mysql database schema


    【解决方案1】:

    您可以在表格中列出看不见的消息,一旦显示消息,您就可以从表格中删除该行。您也可以在 X 周后删除行,无论用户是否看到这些消息。这将防止表格无限增长。我在想象这样的表格:

    消息 -------- 输入主键 文本 TEXT 看不见的消息 -------------- id 主键 消息类型外键 用户外键 到期日期 DATE

    这个unseenMessages 表将保存系统中的所有消息,每个用户每条消息一次。当用户加载页面时,您检查他们在此表中是否有任何条目。如果是这样,您将显示这些消息,然后将它们从表中删除。把它想象成一个消息“收件箱”。

    另外,我不会做任何涉及动态表创建的事情。你不应该,永远*动态创建表。永远。

    * 当然,临时表除外。

    您的所有消息都应该存储在一个表中,或者至少是固定数量的预定义表中。动态创建表是一个主要的数据库罪恶。动态添加和删除列也是如此。您只是不动态更改数据库架构。在上流社会,你不会这样做。如果您认为必须这样做,则说明您没有正确设计数据库。

    编程类比是eval() 函数:它只是其中一个几乎从来都不是一个好主意的东西。平心而论,eval() 在某些情况下是可以的。永远不会动态创建表。

    【讨论】:

    • 你能再解释一下删除方法吗?我想我不理解你的架构。您究竟在提议什么 - 为每个用户删除消息的未见消息表,或者在新用户加入时添加用户的主表,然后将其删除?在表中添加和删除用户似乎比仅仅添加更多的工作。
    • 另外,我对为什么不进行动态表创建有点困惑。假设我有一个一次性消息表,将在用户下次登录时显示。如果我要走每条消息 1 个“已见”表的路线,为什么不将其编码到管理后端界面而不是让启动一个像 phpMyAdmin 这样的工具——它几乎可以做同样的事情?
    • 推测“seen”表将具有用户表和消息表的外键。如果您动态创建它,数据库将发出一个模式锁,这将导致阻塞并很可能导致进程死锁。
    • 那么,如果我动态创建一个新的空表,其中包含两列 user_id 和 message_id(均为外键),是否足以锁定系统?我可以获得有关此的参考,以便我可以阅读更多有关此的信息吗?如果必须将系统锁定在一张空表上,这似乎是一个糟糕的设计,目前还没有什么可以验证的。从某种意义上说,您只是在建立未来的约束,而不是现有的约束。我不声称知道必须如何编写数据库软件,但似乎没有必要这样做。
    • 约翰,感谢您的努力。我真的这样做了,但仍然有一些悬而未决的问题。使用删除路由,我必须为每条新消息预先填充所有现有用户的表,并为每个新用户将新用户添加到该表中。为什么这会比我原来的提议更好?这似乎比使用 user_id 和 message_id 查找的单个可见表要多得多。
    【解决方案2】:

    这些信息有多重要?如果它们真的只是“嘿,这是新事物”的一种观点,那么您是否知道每个人是否都看到它们是否重要? (但也许您想衡量有效性?)为什么不只显示一周或一个月或您的普通用户登录的任何时间范围。对于那些真正感兴趣的人,任何关键的站点更新都可以放在单独的更改日志页面上。如果有特价,那么它只是时间限制,为什么用户不希望每次登录时都被提醒呢?或者,您可以将主页(或链接)的一部分专门用于网站上的新内容,如果用户在上次更新后点击了它,则将其记录在 cookie 中,如果没有,则为该用户突出显示它。很抱歉乱码回复。

    【讨论】:

      【解决方案3】:

      你可以有一个用户,一条消息, 和看到/确认的消息 桌子。当用户确认 消息,我们在 看到带有用户 ID 和消息 ID 的表 对。

      这似乎很合理。

      但是,seen table 会增长 随着用户数量和 消息。在某些时候,这将 变得笨拙(任何洞察力 将用于 a 上的单个 mysql 数据库 单服务器?)。

      根据您所说的用户数量,除非您经常发送大量消息,否则我不会打赌这是一个问题。如果停用消息是有意义的,您可以在消息上设置一个 disabled 标志,并在后台作业中从已看到的表中删除对应于已禁用消息的行(仓库!)。

      性能方面,很多都取决于服务器的规格以及它在做什么。即使有很多(成千上万的)行和一些配置调整,您也可以从索引良好的简单表中获得很多性能。

      如果您想在个人/组级别控制谁可以看到消息,John Kugelman 的解决方案(每个用户每条消息 1 个条目)更有意义。

      这些技术也不是相互排斥的。

      更新: 同意不创建动态表。 :)

      【讨论】:

        【解决方案4】:

        对于现代 RDBMS,您的音量并不吓人。请记住,Twitter 的 MySQL 数据库以及其他 SQL Server 和 Oracle 数据库中有数以百万计的记录。

        我可以看到两种方法来实际解决这个问题

        1. 为特定消息设置一个独特的 cookie,如果这些消息很少见,这很好

        2. 创建几个表来保存消息详细信息

          消息 - 将保存消息定义,包括消息文本(或在您的情况下为 HTML?),以及活动/非活动的消息状态。

          用户消息 - 交叉引用 如果用户包含行的表 已查看消息。当。。。的时候 用户看到并确认消息 你可以在其中插入一行 桌子。

          判断用户是否 是否应该看到消息,你 将查询此表和 带有用户 ID 的活动消息。 如果返回结果,那么您 应该绕过消息,否则 显示它..

        我认为这为您提供了一个很好地扩展到未来的机会,因为“用户消息”表只是用户/帐户表和消息表之间的整数关联键。您还可以在用户消息表上记录用户的处置(确认、查看、绕过等...)

        如果不清楚,请告诉我,我可以尝试更好地解释或提供图表。我敢肯定还有其他一些模式可以做到这一点。大约每个月左右登录一次我的在线账户后,美国银行都会闪现这些东西。

        【讨论】:

          【解决方案5】:

          这是我的方法:

          CREATE TABLE IF NOT EXISTS `system_user_messages` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `user_id` int(11) NOT NULL,
            `section` enum('home','account','all') NOT NULL DEFAULT 'home',
            `message` varchar(250) NOT NULL,
            `message_type` varchar(25) NOT NULL,
            `show` tinyint(4) NOT NULL DEFAULT '1',
            `allow_dismiss` tinyint(4) NOT NULL DEFAULT '1',
            `created_on` datetime NOT NULL,
            `dismissed_on` datetime DEFAULT NULL,
            `show_order` int(11) NOT NULL DEFAULT '0',
            PRIMARY KEY (`id`),
            KEY `idx-user_id` (`user_id`),
            KEY `idx-section` (`section`),
            KEY `message_type` (`message_type`)
          );
          

          我添加了allow_dismiss,因为您可能不想让用户关闭该消息。在我的情况下,当某些用户的 CC 即将到期时,我们不允许关闭,然后一旦用户更新 CC 信息,系统就会删除该消息。另一方面,您可能还希望仅在网站的某些区域显示消息。

          我发布了 sql,因为我认为这种方式很清楚......我知道对这个架构有很多改进,但也许会给你一个想法。

          【讨论】:

          • 我喜欢这个,因为它允许您根据某些细分活动来定位接收消息的用户。
          猜你喜欢
          • 1970-01-01
          • 2021-06-06
          • 2011-01-19
          • 1970-01-01
          • 2017-02-25
          • 1970-01-01
          • 2010-10-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多