Ray*_*Ray 4 mysql database-design comments photo polymorphic-associations
我正在建立一个类似于Yelp(推荐引擎,虽然规模较小)的网站,因此系统中将有三个主要实体:用户,地方(包括商家)和活动.
现在我想知道的是如何为每种类型的实体存储照片,评论和"赞美"(类似于Facebook的"赞")等信息,以及它们可以应用于每个对象的信息(例如评论推荐,照片等).现在,我这样做的方式是每个ie的单个表
类型表示的照片(id,type,owner_id,is_main等等)
:1 =用户,2 =地点,3 =事件注释(id,object_type,object_id,user_id,content等等)
,其中object_type可以是一些不同的对象,如照片,推荐等Compliment(object_id,object_type,compliment_type,user_id)
其中object_type可以是一些不同的对象,如照片,推荐等Activity(id,source,source_type,source_id等等)
//for "activity feed"
,其中source_type是用户,地点或事件通知(id,收件人,发件人,activity_type,object_type,object_id等等)
,其中object_type和object_id将用于提供与通知对象的直接链接,例如用户的照片被称赞
但是在 阅读 SO上的一些帖子之后,我意识到我无法使用外键保持参照完整性,因为这需要1:1的关系,而我的source_id/object_id字段可以与多个表中的ID相关.所以我决定采用保持主实体的方法,然后将其分解为子集,即
User_Photo(photo_id,user_id)| Place_Photo(photo_id,place_id)| 等等...
Photo_Comment(comment_id,photo_id)| Recommendation_Comment(comment_id,rec_id)| 等等...
赞美(id,...)
//would need to add a surrogate key to Compliment table now
Photo_Compliment(compliment_id,photo_id)| Comment_Compliment(compliment_id,comment_id)| 等等...
User_Activity(activity_id,user_id)| Place_Activity(activity_id,place_id)| 等等...
我以为我可以创建将每个子表连接到主表的视图,以获得我想要的结果.另外我认为它也适合我在Code Igniter中的对象模型.
我认为唯一可以离开的表是通知表,因为有很多对象类型(论坛帖子,照片,推荐等等),这个表只会保留一周的通知,所以任何参考完整性问题都不应该是'这是一个很大的问题(我认为).
我是否以明智的方式解决这个问题?我可能忽略的任何性能,可靠性或其他问题?
我能看到的唯一"问题"是我最终会得到很多表(因为现在我有大约72个,所以我想在添加额外内容之后我最终会得到一些不到90个表),就我所知,这不是问题.
非常感谢任何反馈.提前致谢.
编辑:为了清楚起见,我并不担心我最终还有10张桌子.据我所知,表的数量并不是太大的问题(一旦它们被使用)......除非你说200左右:/
这个UoD(话语世界)的一些命题
引入对象ID
只是事实类型
现在提取谓词
Predicate Predicate Arity
---------------------------------------------
... logged in 1 (Unary predicate)
... uploaded ... 2 (Binary)
... exists 1 (Unary)
... is of ... 2 (Binary)
... created ... on ... 3 (Ternary)
Run Code Online (Sandbox Code Playgroud)
看起来每个命题都是这个UoD可以用最大三元谓词来表达,所以我建议像
谓词角色 (Role_1_ID, Role_2_ID, Role_3_ID)
是对象在谓词中扮演的角色.用从左到右...
的谓词替换谓词Role_ID
.请注意,仅Role_1_ID
强制(至少一元谓词),其他两个可能为NULL.
在这个简单的模型中,可以提出任何建议.因此,您需要在应用程序层上实现约束.例如,你必须确保它可以创建Comment
的Place
,但不能创建Place
上Place
.并非所有谓词都代表动作,例如... logged in
动作而... is of ...
不是动作.所以,你的活动料将列出所有Propositions
与Predicate.IsAction = True
.
如果你稍微重新安排一下,你就可以简化你的评论和赞美。本质上,您希望拥有一组评论和另一组赞美。您的问题是,这不允许您使用声明性引用完整性(外键约束)。
解决这个问题的方法是确保能够吸引评论和赞美的对象都是一种超类型的逻辑子类型。从逻辑角度来看,这意味着您有一个“THING_OF_INTEREST”实体(我在这里不提出命名约定建议!),并且每一个吸引评论和赞美的具体事物都将是 THING_OF_INTEREST 的子类型。因此,您的评论表将有一个“thing_of_interest_id”FK 列,您的赞美表也类似。您仍将拥有子类型表,但它们将与 THING_OF_INTEREST 具有 1:1 FK。换句话说,THING_OF_INTEREST 的作用是为您提供单个主键域,而所有子类型表都包含特定于类型的属性。通过这种方式,您仍然可以使用声明性引用完整性来强制您的评论和赞美关系,而不必为不同类型的评论和赞美使用单独的表。
从物理实现的角度来看,最重要的是您感兴趣的各种事物都共享一个共同的主键域。这就是让您的评论表具有单个 FK 值的原因,该值可以轻松地与任何感兴趣的事物连接起来。
根据您如何处理评论和建议,您可能(但可能不需要)需要实际实现 THING_OF_INTEREST - 它将至少有两个属性,主键(通常是 int)加上一个分区属性,告诉您哪个子键-它是什么类型的东西。