У меня есть социальная сеть, похожая на 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