Как получить социальную карту друзей с помощью одного запроса из базы данных sql социальной сети?

У меня есть сайт социальной сети, созданный на основе структуры Elgg (php + mysql). Моя цель - получить всех друзей данного пользователя, а также установить дружеские отношения между этими друзьями.

Вся необходимая мне информация находится в двух таблицах:

  • таблица "пользователи", где пользователи идентифицируются по уникальному идентификатору, называемому guid
  • и таблица «отношений», где отношения друзей представлены тройками (guid_one, «friend», guid_two)

Дружеские отношения в Элгге могут быть как односторонними, так и двунаправленными, это больше похоже на отношения «подписки» в Твиттере. Гарантируется уникальность троек отношений.

Краткий пример: учитывая пользователей (1, «Джо»), (2, «Джек») (3, «Джим») и следующие отношения (1, «друг», 2), (2, «друг», 1) , (1, «друг», 3), (2, «друг», 3), это можно интерпретировать как

  1. Джо и Джек - общие друзья (следите друг за другом)
  2. За Джимом следуют Джо и Джек.

Я бы хотел получить

  • список всех отношений между друзьями для любого данного пользователя
  • в порядке убывания количества отношений (т.е. сначала укажите отношения для тех друзей, которые подписаны на большинство моих друзей)
  • желательно в одном запросе

Что было бы наиболее эффективным способом сделать это?

ИЗМЕНИТЬ Пока у меня есть это:

SELECT
    u1.guid, u1.name, u2.guid, u2.name
FROM
    users u1
INNER JOIN relationships r1 ON 
  (u1.guid = r1.guid_one AND r1.relationship = "friend")
INNER JOIN users u2 ON (r1.guid_two = u2.guid)
INNER JOIN relationships r2 ON 
  ((r2.guid_one = xxx AND r2.guid_two = u1.guid) 
  OR (r2.guid_two = xxx AND r2.guid_one = u1.guid))
INNER JOIN relationships r3 ON 
  ((r3.guid_one = xxx AND r3.guid_two = u2.guid) 
  OR (r3.guid_two = xxx AND r3.guid_one = u2.guid))

Где xxx означает руководство пользователя, которое меня интересует. С этим связаны две основные проблемы: он не упорядочен по количеству отношений и очень медленный из-за большого количества объединений. Кроме того, у него есть только односторонние отношения (кто за кем следует из моих друзей) - однако, я думаю, это может быть решено союзом.

Есть идеи по улучшению этого?


person András Szepesházi    schedule 28.04.2011    source источник


Ответы (1)


Вы можете использовать BFS для хранимой процедуры. инициализируйте таблицу с указанным пользователем, и каждый шаг BFS будет вставлять в эту таблицу друзей пользователей в этой таблице. расстояние (или прыжки) может быть параметром этой процедуры.


Изменить: как работает BFS (wikipedia). Как работают хранимые процедуры (mysql), циклы и рекурсия (mysql) и stackoverflow

person Dan    schedule 28.04.2011
comment
Можете ли вы связать меня с любым ресурсом, который более подробно объясняет, как это реализовать? Спасибо! - person András Szepesházi; 28.04.2011
comment
+1 за то, что показал мне BFS, однако предпочтительным решением будет один запрос без использования хранимых процедур. - person András Szepesházi; 29.04.2011
comment
если ваш социальный радиус установлен на 2, вы можете сделать это одним вызовом хранимой процедуры. Я по-прежнему рекомендую использовать хранимую процедуру, потому что вам также необходимо заблокировать таблицу на время итераций, чтобы избежать возврата неверных данных. В любом случае вы не можете сделать это за один раз, и предпочтительны хранимые процедуры, поскольку они отделяют алгоритм от языка, который вы используете в своей бизнес-логике, например Java, Ruby и др. - person Dan; 30.04.2011