根据共同好友推荐好友
Suggest friends based off of mutual friends
我已经在这个站点上四处查看了,但是 none 似乎正是我要找的东西。他们中的很多人都在谈论 Facebook 是如何做的,或者 Twitter 是如何推荐关注者的,但即便如此,他们也没有给出任何直接的答案。
我找到的都是用两个用户ID计算共同好友。
我希望能够获取登录用户的 ID,通过他们的朋友,通过他们的朋友来计算与登录用户拥有最多共同朋友的人,建议人们添加有最多共同的朋友。
我为此使用 PHP 和 MySQL。我只是想不通我会怎么做。
我的友谊 table 看起来像这样:
---------------------------------
| friend1 | friend2 | pending |
---------------------------------
| 1 | 2 | 0 |
| 2 | 1 | 0 |
| 3 | 1 | 0 |
| 1 | 3 | 0 |
---------------------------------
这个table表明user_id1是2和3的朋友
并且 2 不是 3 的朋友,而是 1 的朋友。
所以,如果用户登录 user_id 2,我希望它建议 user_id 3,因为他们都是 user_id 1 的朋友。
我目前拥有的:
public function friendList($user_id = null){
if(!$user_id){
$user_id = $this->_data->user_id;
}
$query = "SELECT friend2 FROM user_friends WHERE pending = 0 AND ((friend1 = ".$user_id.") AND (friend2 IN (SELECT user_id FROM users WHERE active = 1 AND user_id = friend2)))";
$data = $this->_db->hardquery($query);
return $data->results();
}
public function suggestUsers(){
$user_id = $this->_data->user_id;
$my_friends = array();
$suggest_friends = array();
foreach($this->friendList() as $friend){
array_push($my_friends,$friend->friend2);
}
foreach($my_friends as $friend_id){
foreach($this->friendList($friend_id) as $friendOfFriend){
$friendOfFriend = $friendOfFriend->friend2;
if(!in_array($friendOfFriend,$my_friends) && $friendOfFriend != $user_id){
array_push($suggest_friends,$friendOfFriend);
}
}
}
foreach($suggest_friends as $sgf){
$sgf = new user($sgf);
$sgf = $sgf->data();
echo "<a href=\"#\">".$sgf->display."</a><br>";
}
}
它起作用了,列出了用户朋友的朋友,但没有添加用户...
但是,我无法根据谁拥有最多的共同朋友来对它进行排序,我想这没问题(尽管我希望可以),
但它似乎也不是一个非常有效的方法方法..
这似乎需要大量资源才能遍历用户的所有朋友,尤其是如果用户添加了几百到一千个朋友,而他们又添加了几百到一千个,等等
我对高级 SQL 不是很熟悉,所以我不确定我会怎么做。
您可以通过单个 sql 查询来做到这一点。您应该为此编写 sql 内部子查询。看下面的查询。它 returns 给定登录用户 ID 时的共同朋友 ID。
$sql= "SELECT `friend2` FROM `user_friends` WHERE `friend1` IN (SELECT `friend2` FROM `user_friends` WHERE `friend1`=$logged_in_user_id) AND `friend2` != $logged_in_user_id";
只需为变量 $logged_in_user_id
传递登录用户 ID。如果你想知道如何编写 sql 子查询,你可以通过查看 Sql Sub Queries link.
来学习
以下函数将输出共同好友数据。
public function testSuggest(){
$logged_in_user_id = $this->_data->user_id;
$suggest_friends = array();
$sql = "SELECT `friend2` FROM `user_friends` WHERE `friend1` IN (SELECT `friend2` FROM `user_friends` WHERE `friend1`=$logged_in_user_id) AND `friend2` != $logged_in_user_id AND `friend2` IN (SELECT `user_id` FROM `users` WHERE `active`=1 AND `user_id` = `friend2`)";
$data = $this->_db->hardquery($sql);
foreach($data->results() as $mutuals){
array_push($suggest_friends,$mutuals);
}
foreach($suggest_friends as $sgf){
$sgf_user = new user($sgf);
$sgf_user_data = $sgf_user->data();
echo "<a href=\"".config::get('site/url')."/u/".$sgf_user_data->username."\">".$sgf_user_data->display."</a><br>";
}
}
这是尝试通过 1 个查询执行此操作。这个想法是 select friend2
列表,并将其加入 select,其中 friend2
是 friend1
。使用 GROUP BY
,然后我们能够 return 按友谊的相关性以及与该人成为朋友的每个人排序的行。
SELECT
a.friend2,
COUNT(*) as relevance,
GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
user_friends a
JOIN
user_friends b
ON (
b.friend2 = a.friend1
AND b.pending = 0
AND b.friend1 = LOGGED_IN_USER
)
WHERE
a.pending = 0
AND
a.friend2 != LOGGED_IN_USER
GROUP BY
a.friend2
ORDER BY
relevance DESC;
一个sqlFiddle example - http://sqlfiddle.com/#!9/3dbf0/3
编辑
在我最初的查询中,我忘记排除任何已经是 LOGGED_IN_USER
好友的用户。通过在不存在友谊的地方使用 LEFT JOIN
和 IS NULL
,这应该 return 您想要的结果。
SELECT
a.friend2,
COUNT(*) as relevance,
GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
user_friends a
JOIN
user_friends b
ON (
b.friend2 = a.friend1
AND b.pending = 0
AND b.friend1 = LOGGED_IN_USER
)
LEFT JOIN
user_friends c
ON
(
c.friend2 = a.friend2
AND c.pending = 0
AND c.friend1 = LOGGED_IN_USER
)
WHERE
a.pending = 0
AND
c.friend1 IS NULL
AND
a.friend2 != LOGGED_IN_USER
GROUP BY
a.friend2
ORDER BY
relevance DESC;
我已经在这个站点上四处查看了,但是 none 似乎正是我要找的东西。他们中的很多人都在谈论 Facebook 是如何做的,或者 Twitter 是如何推荐关注者的,但即便如此,他们也没有给出任何直接的答案。
我找到的都是用两个用户ID计算共同好友。
我希望能够获取登录用户的 ID,通过他们的朋友,通过他们的朋友来计算与登录用户拥有最多共同朋友的人,建议人们添加有最多共同的朋友。
我为此使用 PHP 和 MySQL。我只是想不通我会怎么做。
我的友谊 table 看起来像这样:
---------------------------------
| friend1 | friend2 | pending |
---------------------------------
| 1 | 2 | 0 |
| 2 | 1 | 0 |
| 3 | 1 | 0 |
| 1 | 3 | 0 |
---------------------------------
这个table表明user_id1是2和3的朋友
并且 2 不是 3 的朋友,而是 1 的朋友。
所以,如果用户登录 user_id 2,我希望它建议 user_id 3,因为他们都是 user_id 1 的朋友。
我目前拥有的:
public function friendList($user_id = null){
if(!$user_id){
$user_id = $this->_data->user_id;
}
$query = "SELECT friend2 FROM user_friends WHERE pending = 0 AND ((friend1 = ".$user_id.") AND (friend2 IN (SELECT user_id FROM users WHERE active = 1 AND user_id = friend2)))";
$data = $this->_db->hardquery($query);
return $data->results();
}
public function suggestUsers(){
$user_id = $this->_data->user_id;
$my_friends = array();
$suggest_friends = array();
foreach($this->friendList() as $friend){
array_push($my_friends,$friend->friend2);
}
foreach($my_friends as $friend_id){
foreach($this->friendList($friend_id) as $friendOfFriend){
$friendOfFriend = $friendOfFriend->friend2;
if(!in_array($friendOfFriend,$my_friends) && $friendOfFriend != $user_id){
array_push($suggest_friends,$friendOfFriend);
}
}
}
foreach($suggest_friends as $sgf){
$sgf = new user($sgf);
$sgf = $sgf->data();
echo "<a href=\"#\">".$sgf->display."</a><br>";
}
}
它起作用了,列出了用户朋友的朋友,但没有添加用户...
但是,我无法根据谁拥有最多的共同朋友来对它进行排序,我想这没问题(尽管我希望可以),
但它似乎也不是一个非常有效的方法方法..
这似乎需要大量资源才能遍历用户的所有朋友,尤其是如果用户添加了几百到一千个朋友,而他们又添加了几百到一千个,等等
我对高级 SQL 不是很熟悉,所以我不确定我会怎么做。
您可以通过单个 sql 查询来做到这一点。您应该为此编写 sql 内部子查询。看下面的查询。它 returns 给定登录用户 ID 时的共同朋友 ID。
$sql= "SELECT `friend2` FROM `user_friends` WHERE `friend1` IN (SELECT `friend2` FROM `user_friends` WHERE `friend1`=$logged_in_user_id) AND `friend2` != $logged_in_user_id";
只需为变量 $logged_in_user_id
传递登录用户 ID。如果你想知道如何编写 sql 子查询,你可以通过查看 Sql Sub Queries link.
以下函数将输出共同好友数据。
public function testSuggest(){
$logged_in_user_id = $this->_data->user_id;
$suggest_friends = array();
$sql = "SELECT `friend2` FROM `user_friends` WHERE `friend1` IN (SELECT `friend2` FROM `user_friends` WHERE `friend1`=$logged_in_user_id) AND `friend2` != $logged_in_user_id AND `friend2` IN (SELECT `user_id` FROM `users` WHERE `active`=1 AND `user_id` = `friend2`)";
$data = $this->_db->hardquery($sql);
foreach($data->results() as $mutuals){
array_push($suggest_friends,$mutuals);
}
foreach($suggest_friends as $sgf){
$sgf_user = new user($sgf);
$sgf_user_data = $sgf_user->data();
echo "<a href=\"".config::get('site/url')."/u/".$sgf_user_data->username."\">".$sgf_user_data->display."</a><br>";
}
}
这是尝试通过 1 个查询执行此操作。这个想法是 select friend2
列表,并将其加入 select,其中 friend2
是 friend1
。使用 GROUP BY
,然后我们能够 return 按友谊的相关性以及与该人成为朋友的每个人排序的行。
SELECT
a.friend2,
COUNT(*) as relevance,
GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
user_friends a
JOIN
user_friends b
ON (
b.friend2 = a.friend1
AND b.pending = 0
AND b.friend1 = LOGGED_IN_USER
)
WHERE
a.pending = 0
AND
a.friend2 != LOGGED_IN_USER
GROUP BY
a.friend2
ORDER BY
relevance DESC;
一个sqlFiddle example - http://sqlfiddle.com/#!9/3dbf0/3
编辑
在我最初的查询中,我忘记排除任何已经是 LOGGED_IN_USER
好友的用户。通过在不存在友谊的地方使用 LEFT JOIN
和 IS NULL
,这应该 return 您想要的结果。
SELECT
a.friend2,
COUNT(*) as relevance,
GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
user_friends a
JOIN
user_friends b
ON (
b.friend2 = a.friend1
AND b.pending = 0
AND b.friend1 = LOGGED_IN_USER
)
LEFT JOIN
user_friends c
ON
(
c.friend2 = a.friend2
AND c.pending = 0
AND c.friend1 = LOGGED_IN_USER
)
WHERE
a.pending = 0
AND
c.friend1 IS NULL
AND
a.friend2 != LOGGED_IN_USER
GROUP BY
a.friend2
ORDER BY
relevance DESC;