Друг друга в PHP / MySQL?

У меня есть социальная сеть, похожая на myspace / facebook. В моем коде вы либо друг человека, либо не друг, поэтому я показываю все действия от людей, с которыми вы дружите (в этом посте я буду ссылаться на действия только в виде сообщений, чтобы облегчить визуализацию.

Таким образом, вы каждый раз, когда человек публикует бюллетень, он будет показан любому человеку, который есть друг.

В mysql вы получите список друзей друзей, сделав что-то вроде этого,

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

Я хочу знать, как сайт, похожий на facebook и некоторые другие, будет показывать все сообщения из ваших друзей и друзей ваших друзей?

Если у кого-то есть идея, пожалуйста, покажите какой-нибудь код, например, какой запрос mysql?

Ответ заключается в том, что они не делают выборки в таблице друзей, они, скорее всего, используют де-нормированную таблицу новостей. Мы внесли новостной канал, похожий на Facebook на DoInk.com, вот как мы это сделали:

Существует понятие «NewsEvent», оно имеет тип, инициатор (идентификатор пользователя) и целевой пользователь (также идентификатор пользователя). (Вы также можете добавить дополнительные столбцы для других свойств, относящихся к событию, или присоединиться к ним)

Когда пользователь публикует что-то на другой стене пользователя, мы генерируем следующее событие:

 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 

Когда вы хотите видеть новость для всех событий относительно своих друзей, вы можете сделать запрос, выбрав для всех событий, где инициатор находится в вашем наборе друзей.

Избегайте реализаций с подвыборками, в зависимости от сложности, они не будут масштабироваться.

вы выполните подзапрос:

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

Протестируйте оба из них для производительности:

 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 проиндексированы.

Простым подходом было бы сделать какое-то простое вложенное предложение. Так скажите, что у вас есть стол с сообщениями и идентификатор плакатов, а таблица друзей, первый слой будет

 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 

когда пользователь дружит с кем-то, он добавляет, что новый друг в friends_web находится на уровне 0 (так как этот друг не является прочь), то добавляет, что друзья друзей на уровне 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 слой глубоко в сети друзей.

Извините за длинный ответ.

Это должно вытащить все сообщения пользователя пользователя.

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