Таблица отношений пользователей. Как правильно?

Есть таблица пользователей, у всех пользователей есть user_id(например: 111, 222, 333, 444). Требуется добавить таблицу с друзей:
user_id(111) дружит с user_id(333) и user_id(444),
user_id(222) дружит с user_id(444)

Из нагугленного пришел к такой таблице:
user_id | friend_id
222 | 444
444 | 222

Сомневаюсь что так правильно, т.к. для каждой пары друзей создается две записи.
Как сделать лучше чем привел в примере?
  • Вопрос задан
  • 3407 просмотров
Пригласить эксперта
Ответы на вопрос 4
socengel
@socengel
7 лет native php в продакшене, онлайн 20000+,
Правильная таблица отношений:
Отмечу на всякий случай никаких id(самих записей) не должно быть! все выборки по ключам приведенным ниже
user_id|friend_id|relation_id|date(timestamp)
222|444|1|ts
444|222|2(не просто дружит а например встречается, женат, и т.п. для каждого случая свой уникальный id)|ts

первичный ключ составной (user_id,relation_id)
дополнительный ключ (friend_id, relation_id)

если кидают заявку создается 1 запись user_id>friend_id>0

проверка на поступившие заявки friend_id(current_user_id) | relation_id = 0

подтверждение: (должна быть транзакция!) то есть если отвалится один из запросов нужно вернуть все как было.
на MyISAM ручками(средствами PHP проверяем). На innodb делаем транзакцию средствами БД.
вписываем строчку с подтверждением курент_юзер > фриенд_ид > relid - 1 и обновляем основную заявку до единицы. Повторюсь если одна из команд не пройдет надо все откатить.

если отказ то удаляем основную заявку из базы.

по поводу дополнительных отношений:
кинуть заявку можно только пользователю у которого взаимно стоит 1 и проверка собственно на заявки
friend_id(current_user_id) | relation_id >(больше) 1.
Остальной алгоритм тот же. одновременно у 1 пользователя может быть только одна запись с отношением больше 1 (желательно, это как индикатор именно личного отношения, для группировки друзей лучше все же завести отдельное поле)
Описание с реальной базы данных на 30 миллионов пользователей.
Ответ написан
Комментировать
@Yago
Не совсем для каждой пары друзей создается 2 записи.

Создается одна запись на одно предложение дружбы. Она же может быть не взаимной (неподтвержденные предложения не означают дружбу).

Считаю схему таблицы правильной.
Ответ написан
AxisPod
@AxisPod
А по другому вменяемо никак и не сделать.
Ответ написан
NYMEZIDE
@NYMEZIDE
резюме - ivanfilatov.ru
Лучше реализовать хранение друзей не через связи-ключи в другой таблице - а через хранение LIST (любой другой набор) в XML | JSON формате в самой записи.

пример
userid name friendlist requestfriendlist subscrybefriendlist
1111 Ivan {2222, 3333} {4444} {}
2222 Sergey {1111, 3333} {} {4444}
3333 Olga {1111, 2222} {4444} {}
4444 Max {} {2222} {3333, 1111}

в friendlist - хранить подтвержденных друзей.
в requestfriendlist - хранить запросы друзей.
в subscrybefriendlist - подписчиков и т.д.

в коде делать связи на основе списков.

Удобно сериализовать данные и удобно ими оперировать. Перебрасывать из одного списка в другой.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы