2009-12-30 5 views
2

J'ai un réseau social similaire à myspace/facebook. Dans mon code, vous êtes l'ami d'une personne ou pas un ami, donc je montre toutes les actions des gens avec qui vous êtes amis (dans ce post, je ferai référence uniquement aux actions comme des billets de bulletin pour faciliter la visualisation.)Ami d'un ami en PHP/MySQL?

vous chaque fois qu'une personne placarder un bulletin il sera affiché à toute personne qui est là un ami.

Dans MySQL, vous obtiendrez une personne liste d'amis en faisant quelque chose comme ça,

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

Je veux savoir comment un site comme facebook et d'autres afficheraient tous les messages de vos amis et de vos amis f Riends?

Si quelqu'un a une idée s'il vous plaît montrer un code comme quel genre de requête mysql?

Répondre

6

La réponse est qu'ils ne font pas de sélections sur une table d'amis, ils utilisent très probablement une table d'événements de nouvelles normalisée. Nous avons implémenté un fil de nouvelles similaire à Facebook sur DoInk.com, voici comment nous l'avons fait:

Il y a la notion d'un "NewsEvent" il a un type, un initiateur (un user id) et un utilisateur cible (aussi un identifiant d'utilisateur). (Vous pouvez également colonne supplémentaire (s) pour les autres propriétés pertinentes à l'événement, ou se joindre à eux)

Lorsqu'un messages de l'utilisateur quelque chose sur un autre mur utilisateurs nous générons un événement comme celui-ci:

INSERT INTO events VALUES (wall_post_event, user1, user1) 

Lorsque vous consultez le profil de l'utilisateur1, vous devez sélectionner tous les événements pour lesquels l'utilisateur1 est l'initiateur ou la cible. C'est ainsi que vous affichez le flux de profils. (Vous pouvez obtenir la fantaisie et filtrer les événements selon le modèle de votre vie privée, vous pouvez envisager de le faire en mémoire pour des raisons de performance.)

Exemple:

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 

Lorsque vous voulez voir le fil d'actualité pour tous les événements relatifs Pour vos amis, vous pouvez effectuer une sélection de requête pour tous les événements où l'initiateur appartient à votre groupe d'amis.

Évitez les implémentations avec des sous-sélections, en fonction de la complexité, elles ne seront pas mises à l'échelle.

3

vous faites une sous-requête:

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

+0

esprit que vous, je suis sûr que ce n'est pas comment il fait facebook, ils ont beaucoup d'optimisations qu'ils font, et ils utilisent ne certainement pas hors de la base de données relationnelle de conservation. – twolfe18

+1

Devrait probablement DISTINCT que de sorte que vous obtenez seulement un user_id une fois, même si elles semblent être des amis avec ** lots ** de personnes. – GrayWizardx

+0

Ils utilisent MySQL ... – cletus

2

test ces deux performances pour:

SELECT DISTINCT user_id 
FROM friends f1 
JOIN friends f2 ON f1.friend_id = f2.user_id 
WHERE f2.friend_id = 1 

et

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

Souvent, ils sont les mêmes, mais parfois ils » ne pas.

Assurez-vous que friend_id et user_id sont indexés.

+0

+1 pour la version de jointure, que j'aurais tendance à préférer – bobince

1

L'approche simple serait de faire une sorte de clause imbriquée simple.Alors que vous avez une table avec les messages et l'id affiches, et une table d'amis, la première couche serait

SELECT post FROM posts JOIN friends 
    on post.userid = friends.friend_id 
    WHERE friend.id = 1 (user ID) 

puis d'obtenir un des amis d'amis

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) 

Vous pouvez répéter cette imbrication chaque temps que vous voulez ajouter une autre couche d'abstraction d'ami. Le problème avec cette approche est que cela prendrait beaucoup de temps à s'exécuter. A chaque fois que vous ajoutez une couche d'abstraction d'ami, vous augmentez la complexité par une puissance de n (où n est le nombre de lignes dans votre table).

Il est plus probable qu'ils épargnent les amis visibles dans une table quelque part, laisse faire un nouveau déposé appelé friends_web

user_id, friend_id, level 

lorsqu'un quelqu'un d'amis de l'utilisateur, il ajoute que nouvel ami dans friends_web à niveau de 0 (puisque cet ami n'est pas loin) puis ajoute ces amis amis à un niveau de 1 (depuis son 1 ami). Afin de conserver l'intégrité de la table, vous devez également ajouter l'enregistrement inversé. Pour préciser si A ajoute B comme ami et C est un ami de B, les deux documents suivants se sont ajoutés à notre nouvelle table

A, C, 1 
C, A, 1 

depuis maintenant A peut voir C et C peuvent voir A.

maintenant, quand nous voulons une question nous faisons juste

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) 

en faisant que vous minimisé la complexité de votre requête lorsque vous effectuez des recherches post tout en étant capable de regarder plus de 1 couche profonde dans une toile d'ami.

Désolé pour la réponse longue et sinueuse.

0

Cela devrait retirer tous les messages de l'ami de l'utilisateur.

SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1) ORDER BY post_id DESC

Cela devrait retirer tous les messages qui sont l'ami de votre ami.

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