谷歌加圈子的数据库结构?

时间:2011-09-14 05:57:06

标签: mysql database-design one-to-many

我确信谷歌不使用mysql,但在我的情况下,我碰巧使用mysql处理项目,并且具有与圈子非常相似的功能:

  1. 用户可以属于多个圈子
  2. 可以在圈子中添加/删除用户
  3. 帖子可以是公开的,也可以分享给圈子/个人用户
  4. 如果帖子被分享到圈子,并且新用户被添加到此圈子,则该用户也可以查看帖子。
  5. 如果帖子与圈子共享,并且用户从此圈子中删除,则:a。如果他/她在帖子中回复,他/她仍然可以查看该帖子。他/她不能再查看帖子了
  6. 正如您已经看到的,根据上述要求,数据库中有很多内容。如果我真的与圈子和个人用户分享,我可能需要2个One2Many表。如果我通过最初获取每个圈子的用户列表仅与个人用户分享,那么稍后当用户编辑这些圈子时我会遇到麻烦。

    目前,我的左右攻击是仅分享到圈子,甚至为每个用户创建一个仅限用户的圈子

    所以我当前的数据库表看起来有点像这样:

    circle_to_user:

    id
    circle_id
    user_id
    friend_id
    

    后:

    id
    user_id
    is_public
    

    post_to_circle

    id
    post_id
    circle_id
    

    要查询用户可以查看的帖子列表,查询相当复杂,并包含多个联接:

    $q = Doctrine_Query::create()
                ->addSelect('s.*')
                ->addSelect('u.id, u.first_name, u.last_name, u.username, u.avatar')
                ->from('UserStatus s')
                ->leftJoin('s.User u')
                ->orderBy('s.created_at DESC');
    
            $userId = sfContext::getInstance()->getUser()->getUserId();
            if ($userId == $viewUserId) {
                $q->orWhere('s.user_id = ?', $userId);
                $q->orWhere('s.user_id IN (SELECT DISTINCT cu1.friend_id FROM CircleUser cu1 WHERE cu1.user_id = ?) AND s.is_public = ?', array($userId, true));
                $q->orWhere('s.id IN (SELECT DISTINCT(us2.id)
                                                            FROM
                                                                    UserStatus us2 INNER JOIN us2.UserStatusCircles usc2 ON usc2.user_status_id = us2.id
                                                                    INNER JOIN usc2.Circle c2 ON c2.id = usc2.circle_id
                                                                    INNER JOIN c2.CircleUsers cu2 ON cu2.circle_id = c2.id AND cu2.friend_id = ?)', $userId);
            } else {
                $q->orWhere('s.user_id = ? AND s.is_public = ?', array($viewUserId, true));
                $q->orWhere('s.id IN (SELECT DISTINCT(us1.id)
                                                            FROM
                                                                    UserStatus us1 INNER JOIN us1.UserStatusCircles usc1 ON usc1.user_status_id = us1.id AND us1.user_id = ?
                                                                    INNER JOIN usc1.Circle c1 ON c1.id = usc1.circle_id
                                                                    INNER JOIN c1.CircleUsers cu1 ON cu1.circle_id = c1.id AND cu1.friend_id = ?)', array($viewUserId, $userId));
                $q->orWhere('s.id IN (SELECT DISTINCT(us2.id)
                                                            FROM
                                                                    UserStatus us2 INNER JOIN us2.UserStatusCircles usc2 ON usc2.user_status_id = us2.id AND us2.user_id = ?
                                                                    INNER JOIN usc2.Circle c2 ON c2.id = usc2.circle_id
                                                                    INNER JOIN c2.CircleUsers cu2 ON cu2.circle_id = c2.id AND cu2.friend_id = ?)', array($userId, $viewUserId));
            }
    

    我希望以上信息不会太长,我只是想提供很多细节。我的问题是:

    1. 鉴于上述要求,我的实施是否足够好,或者有什么我应该改变以使其更好?
    2. 我想搜索有关此类特定数据库设计问题的文章,但找不到太多,这类数据库设计是否有任何技术术语
    3. 您是否会建议使用其他类型的数据库,或者使用类似弹性的搜索引用帖子,让它处理搜索而不是使用mysql?
    4. 非常感谢您阅读,直到这一点,如果您发现任何我应该更改的内容,以便更容易理解和回答,请告诉我。

3 个答案:

答案 0 :(得分:1)

虽然您的单个用户圈听起来不错,但您将如何在出路时区分它?当你看到一个帖子被分享到一个圈子时,你怎么知道这个圈子是真正的一个还是一个用户?因为我想你想在界面上以不同的方式显示它们。并且您可能需要知道何时从数据库中获取用户不应该编辑它们的假圆圈。

虽然您可能会避免链接到用户,但您现在必须处理特殊圈子案例。我会说你的2 x 1- *表格可以将帖子链接到多个圈子,也可以分别链接到多个用户。

也许是为了鼓励你审查自己的意图并将“朋友”关系放在一边,这可能会增加一个特殊情况,因为我看到你或多或少都在寻找:获取所有公开的帖子或与之共享的帖子我的用户,或与我所在的圈子共享,或者是我回复的帖子。这不是太复杂我不认为你不必在开头或任何事情上得到一个清单。

(在相关的说明中,多个JOIN不是一个突出的问题。更重要的是,你有多个子查询。通常这是坏消息。在大多数情况下,它们可以作为普通连接重新加工,通常更干净)。

答案 1 :(得分:0)

这种问题大部分都是用关系模型解决的,我认为谷歌使用数据存储区,然后它就是bigtable,cassandra和hadoop等价物。

答案 2 :(得分:0)

我也遇到同样的问题,但我可以建议你一些我已经覆盖/完成的东西,不要在帖子表中添加两个表而不是在名为with/circle_id的帖子表中添加列。 而且我还想告诉您,在Public表格中添加一个/或更多默认圈子条目(特别是All Friends/CirclesCircles。 现在你的Post Pickup查询将是这样的。

    $id=$_SESSION["loged_in_user_id"];    
    $sql="SELECT * FROM `posts` as p,`circles` as c WHERE c.circle_create_id=$id and (p.with=c.id or p.with=1)";//p.with columns contain circle id and as i tell first entry will be public
$sql_fier=mysqli_query($sql);
/*-------I think you know how to manipulate fetched data---------*/

在社交网络http://www.funnenjoy.com上连接我(需要注册/登录)