在数据库中实现评论和喜欢

我是个软件开发人员。我喜欢编码,但我讨厌数据库... 目前,我正在创建一个网站,用户将被允许标记为 喜欢(如在 FB) ,标签它和 评论的实体。

为了处理这个功能,我在数据库表设计方面遇到了困难。解决方案是微不足道的,如果我们能做到这一点只为一种类型的事情(如照片)。但是我需要为5个不同的事情启用它(现在,但是我还假设随着整个服务的增长,这个数字可以增长)。

我在这里发现了一些类似的问题,但是没有一个答案是令人满意的,所以我再问一遍这个问题。

问题是,如何正确地、 有效率有弹性设计数据库,使其能够存储不同 桌子喜欢标签的注释。一些设计模式作为答案将是最好的;)

详细描述 : 我有一个 桌子 User与一些用户数据,和3个以上的 桌子: Photo照片Articles物品Places地方。我想让任何登录的用户:

  • 评论这三张表中的任何一张

  • 把他们中的任何一个标记为喜欢的

  • 给他们中的任何一个贴上标签

  • 我还想计算每个元素的“喜欢”数以及使用该特定标记的次数。

1斯特方法 :

A)对于 标签,我将创建一个 桌子 Tag [TagId, tagName, tagCounter],然后我将创建 多对多关系 桌子: Photo_has_tagsPlace_has_tagArticle_has_tag

B)评论也是一样的。

C)我将创建一个 桌子 LikedPhotos [idUser, idPhoto]LikedArticles[idUser, idArticle]LikedPlace [idUser, idPlace]喜欢的数量将由 查询计算(我认为是坏的)。还有..。

我真的不喜欢最后一部分的设计,它闻起来很难闻;)


2方法 :

我将创建一个表 ElementType [idType, TypeName == some table name],由管理员(我)填充,其中的 桌子名称可以是 喜欢评论被标记了。然后我将创建 桌子:

A) LikedElement [idLike, idUser, idElementType, idLikedElement],对于评论和标签也是如此,每个评论和标签都有适当的列。现在,当我想拍一张喜欢的照片时,我会插入:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

地点:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

等等... 我认为第二种方法更好,但我也觉得在这个设计中缺少了一些东西..。

最后,我还想知道哪一个最好的地方存储柜台多少次的元素是喜欢。我只能想到两个办法:

  1. 元素(Photo/Article/Place)表
  2. 通过 select count ()。

我希望我现在对这个问题的解释更加全面。

101367 次浏览

既然您“讨厌”数据库,那么为什么要尝试实现一个数据库呢?相反,请求那些热爱和呼吸这些东西的人的帮助。

否则,请学会热爱您的数据库。一个设计良好的数据库简化了编程,工程的网站,并顺利其持续运作。即使是经验丰富的 d/b 设计师也不会有完全和完美的远见: 随着使用模式的出现或需求的变化,将需要一些模式的更改。

如果这是一个单人项目,那么可以使用存储过程将数据库接口编程为简单的操作: add _ user、 update _ user、 add _ comments、 add _ like、 load _ photo、 list _ comments 等。甚至不要将模式嵌入到一行代码中。通过这种方式,可以在不影响任何代码的情况下更改数据库模式: 只有存储过程应该知道该模式。

您可能需要多次重构架构。这很正常。不用担心第一次会做得很完美。只要让它足够实用就可以做出初始设计的原型。如果您有充裕的时间,那么就利用一些时间,然后删除模式并重新执行。这是 一直都是更好的第二次。

据我所知。需要几张表。它们之间有许多对许多的关系。

  • 表,该表用标识字段存储诸如姓名、出生日期等用户数据。
  • 存储数据类型的表。这些类型可能是照片、分享、链接。每种类型都必须有一个唯一的表。因此,它们各自的表与此表之间存在关系。
  • 每种不同的数据类型都有自己的表格。例如,状态更新,照片,链接。
  • 最后一个表是存储 id、用户 id、数据类型和数据 id 的多对多关系表。

看看你需要的访问模式。他们有没有让我的设计选择变得特别困难或效率低下?

如果不喜欢需要较少桌子的那个

在这种情况下:

  1. 添加注释: 您可以选择一个特定的多/多表,或者将其插入到一个公共表中,该表具有所喜欢内容的已知特定标识符,我认为在第二种情况下,客户端代码会稍微简单一些。
  2. 查找项的注释: 在这里,使用公共表似乎稍微容易一些——我们只有一个按实体类型参数化的查询
  3. 查找某人关于一种事物的评论: 任何一种情况下的简单查询
  4. 找到一个人对所有事情的所有评论: 这看起来有点粗糙。

我认为您的“有区别的”方法,选项2,在某些情况下产生更简单的查询,而在其他情况下似乎不会更糟糕,所以我会采用它。

最可扩展的解决方案是只有一个“基本”表(连接到“喜欢”、标记和注释) ,并从中“继承”所有其他表。添加一种新的实体只需要添加一个新的“继承”表——然后它会自动插入到整个类似/tag/comments 的机制中。

实体关系术语是“类别”(参见 欧文方法指南,部分: “子类型关系”)。类别符号是:

Category

假设一个用户可以喜欢多个实体,同一个标记可以用于多个实体,但是注释是特定于实体的,您的模型可以是这样的:

ER Diagram


顺便说一下,大概有3种方法来实现“ ER 类别”:

  • 所有类型在一个表中。
  • 单独表中的所有具体类型。
  • 独立表中的所有具体和抽象类型。

除非您有非常严格的性能要求,否则第三种方法可能是最好的(意味着物理表与上图中的实体1:1匹配)。

考虑对每个实体使用表来进行注释等等。更多的表——更好的分片和缩放。对于我所知道的所有框架来说,控制许多类似的表并不是什么问题。

总有一天,您需要优化这种结构的读取。您可以轻松地在基表之上创建聚合表,并在写操作上损失一些。

有一天,一张带字典的大桌子可能会变得无法控制。

当然可以采用第二种方法,即只有一个表,并为每一行存储元素类型,这将为您提供更多的灵活性。基本上,如果可以用较少的表进行逻辑上的操作,那么使用较少的表几乎总是更好。关于你的案例,我现在想到的一个好处是,考虑到你想删除某个用户的所有喜欢的元素,第一种方法需要为每个元素类型发出一个查询,但是第二种方法只需要一个查询就可以完成,或者当你想添加一个新元素类型时可以考虑,第一种方法涉及为每个新类型创建一个新表,但是第二种方法你不应该做任何事情。

这是一个大概的概念 请不要过多地注意字段名的样式,而应该更多地注意它们之间的关系和结构

enter image description here

这个伪代码将获得 ID 为5的照片的所有注释
从操作中选择 *
WHERE actions.id _ Stuff = 5
和 actions.typeStuff = “ photo”
TypeAction = “ comments”

这个伪代码将得到所有的喜欢或用户谁喜欢的照片与 ID 5
(您可以使用 count ()来获得喜欢的数量)

SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff="photo"
AND actions.typeAction = "like"