在数据库中实现注释和喜欢

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

我遇到了处理这个function的数据库表devise。 解决scheme是微不足道的,如果我们只能为一种types的东西(如照片)做到这一点。 但是我需要为5个不同的事情启用这个function(现在,但是我也假设这个数字会随着整个服务的增长而增长)。

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

问题是,如何正确, 高效弹性地devise数据库,以便它可以存储对不同表格的评论, 喜欢不同的表格标签 。 一些devise模式作为答案将是最好的;)

详细描述 :我有一个 User与一些用户数据,另外3个 :带照片的照片 ,带文章的文章 ,带地方的地方 。 我想启用任何logging的用户来:

  • 评论这3个表格中的任何一个

  • 将其中任何一个标记为喜欢的

  • 用任何标签标记任何一个标签

  • 我也想计算每个元素的喜欢数量以及特定标签被使用的次数。

一种方法

a)对于标签 ,我将创build一个表格 Tag [TagId, tagName, tagCounter] ,然后我将创build多对多的关系Photo_has_tagsPlace_has_tagPlace_has_tag

b)同样重视评论。

c)我将创build一个 LikedPhotos [idUser, idPhoto]LikedArticles[idUser, idArticle]LikedPlace [idUser, idPlace]喜欢的数量将通过查询计算(我认为这是不好的)。 和…

我真的不喜欢这个devise的最后一部分,它给我的气味非常糟糕;)

第二种方法

我将创build一个表格ElementType [idType, TypeName == some table name] ,由pipe理员(我)填写可以被喜欢评论标记的名称。 然后我将创build表格

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) 

等等…我认为第二种方法更好,但是我也觉得在这个devise中缺less一些东西…

最后,我也想知道哪个最好的地方存储柜台多less次是喜欢的。 我只能想到两种方法:

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

我希望我现在对这个问题的解释更彻底。

最可扩展的解决scheme是只有一个“基本”表(连接到“喜欢”,标签和注释),并“inheritance”所有其他表。 添加一种新的实体只需要添加一个新的“inheritance”表 – 然后自动插入到整个/标签/注释机器中。

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

类别

假设用户可以像多个实体一样,同一个标签可以用于多个实体,但注释是特定于实体的,您的模型可能如下所示:

ER图


顺便说一下,大致有三种方法来实现“ER类”:

  • 所有types在一个表中。
  • 所有具体types在单独的表格中。
  • 所有具体和抽象types在单独的表中。

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

既然你“讨厌”数据库,你为什么要实现呢? 相反,向那些热爱和呼吸这种东西的人寻求帮助。

否则,学会爱你的数据库。 一个精心devise的数据库简化了编程,devise了网站,并使其持续运作平稳。 即使是经验丰富的d / bdevise人员也不会有完整和完善的预见:随着使用模式的出现或需求的变化,将需要一些模式的变化。

如果这是一个单人项目,则使用存储过程将数据库接口编程为简单操作:add_user,update_user,add_comment,add_like,upload_photo,list_comments等。不要将模式embedded到一行代码中。 以这种方式,可以更改数据库模式而不影响任何代码:只有存储过程应该知道模式。

您可能需要多次重构架构。 这个是正常的。 不要担心第一次做到完美。 只要使其function足以使初始devise原型。 如果你有足够的时间,可以使用它,然后删除模式并重新执行。 第二次总是更好。

这是一个普遍的想法,请不要太注意字段名称造型,但更多的关系和结构

在这里输入图像描述

这个伪代码将得到ID为5的所有照片评论
SELECT * FROM操作
WHERE actions.id_Stuff = 5
AND actions.typeStuff =“photo”
AND actions.typeAction =“评论”

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

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

据我所理解。 几个表是必需的。 他们之间有很多关系。

  • 用姓名,姓氏,出生年月等用户数据用同一字段存储的表。
  • 表存储数据types。 这些types可能是照片,分享,链接。 每种types都必须有一个唯一的表格。 因此,他们各自的桌子和这个桌子之间有一个关系。
  • 每个不同的数据types都有它的表格。 例如,状态更新,照片,链接。
  • 最后一个表是存储一个id,用户id,数据types和数据id的多对多关系。

看看你将需要的访问模式。 他们中的任何一个似乎是使我的一个deviseselect或其他方面特别困难或低效?

如果不喜欢那些需要较less表格的

在这种情况下:

  1. 添加注释:您可以select特定的许多/多个表,也可以将其插入公共表中,并为已知的特定标识符插入正在使用的标识。我认为在第二种情况下,客户端代码会稍微简单一些。
  2. 查找项目的注释:这里看起来使用一个公共表格稍微简单一点 – 我们只是通过实体types参数化一个查询
  3. find一个人关于一种事情的评论:在任何情况下简单的查询
  4. 查找一个人对所有事情的所有评论:这似乎有点粗糙无论哪种方式。

我认为你的“歧视”方法(scheme2)在某些情况下会产生更简单的查询,而其他情况下则不会更糟糕,所以我愿意跟它一起去做。

绝对要用第二种方法,你有一个表,并为每一行存储元素types,它会给你更多的灵活性。 基本上,当逻辑上用less数表来完成某些事情时,使用较less的表几乎总是更好。 我现在想到的一个好处就是你要删除某个特定用户的所有喜欢的元素,首先你需要为每个元素types发出一个查询,但是第二种方法可以完成只有一个查询或考虑何时添加一个新的元素types,第一种方法是为每个新的types创build一个新的表格,但是第二种方法你不应该做任何事情…

考虑使用每个实体的表来进行评论等。更多的表 – 更好的分片和缩放。 为我所知的所有框架控制许多类似的表并不是一个问题。

有一天,你需要优化这种结构的读取。 你可以很容易地创build基本的表格,并在写入时丢失一点。

有一本字典的大桌子有一天可能变得无法控制。