社交网络中的活动流的数据库模式和查询

问题描述 投票:2回答:2

作为序言,我不是DBA或SQL专家。但我接受了一个个人项目,要求我在制作社交网络时戴上帽子。 (不,我不是要重新发明Facebook。我的目标是一个利基观众。)是的,我听说过像http://activitystrea.ms/这样的框架,但我觉得数据序列化应该是我需要的最后手段。

无论如何,How to implement the activity stream in a social network帮助我开球,但我有一些悬而未决的问题。

下面是我的数据库模式(为简化起见,省略了一些行):

行动表:

id    name
-------------
1     post
2     like
3     follow
4     favorite
5     tag
6     share

活动表:

id             (int)
user_id        (int)
action_id      (tinyint)
target_id      (int)
object_id      (tinyint)
date_created   (datetime)

object_id指的是target_id是哪种对象类型。这里的想法是表示(用户+动作+目标对象)

  • 用户帖子媒体
  • 用户收藏夹场景
  • 用户关注用户

对象(类型)表:

id    name
-------------
1     media
2     scene
3     brand
4     event
5     user

这里的问题是每个object都有自己独立的表。例如:

媒体表:

id            (int)
type          (int)
thumbnail     (varchar)
source        (varchar)
description   (varchar)

活动表:

id        (int)
user_id   (int)
name      (varchar)
city      (int)
address   (varchar)
starts    (time)
ends      (time)
about     (varchar)

用户表:

id                (int)
username          (varchar)
profile_picture   (varchar)
location          (int)

那么,什么是查询该数据库的最佳(即最有效)方式?

显然我可以在SELECT表上执行activity语句,然后 - 基于object_id - 在PHP中使用条件逻辑来对相应的object表(例如,media)进行单独查询。

或者在所有5个JOIN表上实现某种左或内object更聪明(也更有效),如下所示:MySQL if statement conditional join。我并不完全熟悉JOINS的工作方式,以及SQL是否足够聪明,只能扫描每个object行的相应activity表,而不是所有连接的表。

当然,第一个解决方案意味着对数据库的更多调用,这是不太理想的。但是,我不确定如何在没有实现某些条件逻辑的情况下在一个查询中检索所有相关列(例如,media“source”,event“address”)。

php mysql sql database social-networking
2个回答
4
投票

假设您稍微更改了活动表:

活动表:

id             (int)
user_id        (int)
action_id      (tinyint)
object_id      (tinyint)
date_created   (datetime)

和每个目标类型的连接表:

activity_id    (int)
target_id      (int)

最后你的目标表(媒体)

id            (int)
type          (int)
thumbnail     (varchar)
source        (varchar)
description   (varchar)

和目标表(事件)

id        (int)
user_id   (int)
name      (varchar)
city      (int)
address   (varchar)
starts    (time)
ends      (time)
about     (varchar)

现在,您可以选择数据

SELECT
 activity.id,
 activity.user_id,
 activity.action_id,
 action.name,
 activity.object_id,
 object.name,
 media.id as media_id,
 media.type,
 media.thumbnail,
 media.source,
 media.description,
 event.id as event_id,
 event.name,
 ...
FROM
 activity
 LEFT JOIN action ON (action.id = activity.action_id)
 INNER JOIN mediaToActivity ON (mediaToActivity.activity_id = activity.id)
 LEFT JOIN media ON (media.id = mediaToActivity.target_id)
 INNER JOIN eventToActivity ON (eventToActivity.activity_id = activity.id)
 LEFT JOIN event ON (event.id = eventToActivity.target_id)

使用此查询,您应该在一个查询中获取所有行(但只有实际存在的行填充数据)

注意,我现在还没有测试过这个...


0
投票

我从你的讨论中拼凑出你的解决方案。 Fiddle

create table activity (
  id            int,   
  user_id       int,
  action_id     int,
  target_id     int,
  object_id     int,
  date_created  datetime
);
create table action (
  id int,
  name varchar(80)
);
create table object (
  id int,
  name varchar(80)
);
create table media (
  id int,
  type int,
  thumbnail varchar(255),
  source varchar(255),
  description varchar(255)
);
create table event (
  id       int,
  user_id   int,
  name      varchar(255),
  city      int,
  address   varchar(255),
  starts    time,
  ends      time,
  about     varchar(255)
);

-- setup
insert into action values (1, "post");
insert into object values (1, "media");
insert into object values (2, "event");

-- new event
insert into event values (1, null, "breakfast", null, "123 main st", null, null, "we will eat");
insert into activity values (1, null, 1, 1, 2,  null);

-- new media
insert into media values (1, null, null, null, "new media");
insert into activity values (2, null, 1, 1, 1,  null);

SELECT *
FROM
 activity
 left join event on (event.id = activity.target_id and activity.object_id = 2)
 left join media on (media.id = activity.target_id and activity.object_id = 1);
© www.soinside.com 2019 - 2024. All rights reserved.