PHP / MySQL中朋友的朋友?

时间:2009-12-30 01:07:49

标签: php mysql facebook

我有一个类似于myspace / facebook的社交网络。在我的代码中,你要么是一个人的朋友,要么不是朋友,所以我展示了你与朋友在一起的所有行为(在这篇文章中,我将单独的行动称为公告栏,以便更容易想象。

因此,每当一个人发布公告时,它都会显示给任何有朋友的人。

在mysql中,你可以通过做这样的事情获得一个人朋友列表,

SELECT user_id FROM friends WHERE friend_id = 1 (user ID)

我想知道像Facebook和其他网站这样的网站会如何显示您朋友和朋友的朋友发布的所有公告?

如果有人有想法,请显示一些代码,比如什么样的mysql查询?

5 个答案:

答案 0 :(得分:6)

答案是他们没有在朋友桌上做选择,他们很可能使用非规范化的新闻事件表。我们在DoInk.com上实现了类似于Facebook的新闻提要,以下是我们如何做到的:

有一个“NewsEvent”的概念,它有一个类型,一个发起者(一个用户ID)和一个目标用户(也是一个用户id)。 (您还可以为与事件相关的其他属性添加其他列,或将其加入)

当用户在其他用户墙上发布内容时,我们会生成如下事件:

INSERT INTO events VALUES (wall_post_event, user1, user1)

查看user1的配置文件时,您将选择user1为发起者或目标的所有事件。这就是您显示配置文件供稿的方式。 (根据您的隐私模型,您可以获得想象并过滤掉事件。出于性能原因,您可以考虑在内存中执行此操作)

示例:

SELECT * FROM events WHERE initiator = user1 or target = user1 //to see their profile feed

SELECT * FROM events WHERE initiator IN (your set of friend ids) //to see your newsfeed

如果您想查看与您的朋友相关的所有活动的新闻源,您可以查询选择发起人在您的朋友集中的所有事件。

避免使用子选择实现,具体取决于复杂性,它们不会扩展。

答案 1 :(得分:3)

你做了一个子查询:

SELECT DISTINCT user_id FROM friends WHERE friend_id IN (SELECT user_id FROM friends WHERE friend_id = 1)

答案 2 :(得分:2)

测试这两者的性能:

SELECT DISTINCT user_id
FROM friends f1
JOIN friends f2 ON f1.friend_id = f2.user_id
WHERE f2.friend_id = 1

SELECT DISTINCT user_id
FROM friends
WHERE friend_id IN (SELECT user_id FROM friends WHERE friend_id = 1)

通常它们是相同的,但有时它们不是。

确保将friend_id和user_id编入索引。

答案 3 :(得分:1)

简单的方法是做一些简单的嵌套子句。所以说你有一个包含帖子和海报id的表,以及一个朋友表,第一层就是

SELECT post FROM posts JOIN friends 
  on post.userid = friends.friend_id 
  WHERE friend.id = 1 (user ID)
然后去找朋友的朋友

SELECT post FROM posts JOIN
   (SELECT DISTINCT friends_2.friend_id FROM friends AS friends_1 
        JOIN friends as friends_2 
        on friends_1.friend_id = friends_2.id where friends_1.id = 1) 
AS friends 
wHERE post.userid = friends.friend_id AND mainid = 1 (user ID)

每次要添加另一层朋友抽象时,您都可以重复此嵌套。这种方法的问题是执行需要很长时间。每次添加一层朋友抽象时,你的复杂性都会增加n的幂(其中n是表中的行数)。

他们更有可能将可查看的朋友保存在某个地方的某个表格中,所以让我们创建一个名为friends_web的新表格

user_id, friend_id, level

当用户与某人交朋友时,它将该新朋友添加到0级的friends_web中(因为该朋友不在其他人之外),然后将该朋友朋友添加到1级(因为其1个朋友离开)。为了保持表的完整性,您还需要添加反转记录。为了澄清A是否将B添加为朋友而C是B的朋友,以下两个记录将添加到我们的新表中

A, C, 1
C, A, 1

因为现在A可以看到C和C可以看到A.

现在,当我们想要查询时,我们只需

 SELECT post FROM posts 
  JOIN friends_web ON post.user_id = friends_web.friend_id 
  WHERE friends_web.user_id = user_id AND friends_web.level < 2 (or however deep you want to look)
通过这样做,您可以在进行查找时最大限度地降低查询复杂性,同时能够在朋友网络中查看更多1层深度。

对不起,回复很长。

答案 4 :(得分:0)

这应该取出所有用户的朋友的帖子。

SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1) ORDER BY post_id DESC

这应该删除你朋友朋友的所有帖子。

SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1)) ORDER BY post_id DESC