J'essaie de concevoir un modèle de données qui indique qu'un utilisateur est l'ami d'un autre utilisateur. C’est ce que j’ai trouvé jusqu’à présent, mais cela semble maladroit, existe-t-il une meilleure solution?
User
=====
Id
Name
etc...
UserFriend
===========
UserId
FriendId
IsMutual
IsBlocked
UserRelationship
====
RelatingUserID
RelatedUserID
Type[friend, block, etc]
Convenez que la mutualité n'appartient pas à une colonne; rompt la normalisation.
Pour aller un enregistrement pour deux utilisateurs et éviter de consommer plus de mémoire que les méthodes proposées ne suggèrent (deux fois plus que nécessaire, car il existe deux enregistrements pour chaque utilisateur), vous pouvez procéder comme suit:
Structure de la table:
USER_RELATIONSHIP {
user_first_id,
user_second_id,
type
primary key(user_first_id, user_second_id)
}
Assurez-vous que: user_first_id < user_second_id
La partie la plus intéressante - type
: pour tous les états possibles d’une relation, vous créez les valeurs correspondantes. Par exemple:
pending_first_second
pending_second_first
friends
block_first_second
block_second_first
block_both
Ce que tu as:
user_first_id < user_second_id
garantit qu'il n'y a qu'un seul enregistrement D'une relation entre deux utilisateurs donnés, car cette contrainte et les contraintes de clé primaire Ne permettent pas de le placer autrement.Pour connaître la relation entre deux utilisateurs (ainsi que la mise à jour), il vous suffit de lancer une seule requête:
select * from USER_RELATIONSHIP where
user_first_id = user1_id and
user_second_id = user2_id;
sans une instruction or
qui vérifierait cette colonne vice-versa, ce qui est plus rapide.
Exemple de scénario :
no record
: ne sont pas en couple
pending_first_second
: le premier a fait une demande d'ami au second
friends
: le second a approuvé la demande d'ami
no record
: l'un des utilisateurs a retiré l'autre de ses amis
Cette solution est efficace en termes de mémoire et de vitesse, car vous créez, stockez et mettez à jour un seul enregistrement.
Je construis actuellement un site de réseautage social pour un client et j'ai exprimé les choses de cette façon
CREATE TABLE [dbo].[PersonFriend] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Timestamp] DATETIME NOT NULL,
[ChangeUser] NVARCHAR (200) NOT NULL,
[FriendStatusId] TINYINT NOT NULL,
[Person1Id] INT NOT NULL,
[Person2Id] INT NOT NULL,
[Person1RequestTimestamp] DATETIME NOT NULL,
[Person2AcknowledgeTimestamp] DATETIME NULL
);
Chaque personne est stockée dans la table Personne (imaginez cela). Les champs Person1Id et Person2Id sont FK dans la table person. Je garde une liste de statut dans la table FriendStatus pour indiquer si une requête a été demandée, acceptée, refusée, ignorée, etc. Le champ Timestamp est standard dans ma conception pour indiquer la création d'un enregistrement (il s'agit d'un motif utilisé par la classe de persistance de base). ) et son type de dupliqué dans cette table, car Person1RequestTimestamp contient les mêmes données. Je capture également lorsque la personne 2 a vu la demande et a effectué une action (ce qui est indiqué dans FriendStatusId) et la stocke dans le Person2AcknowledgeTimestamp).
L'une des hypothèses fondamentales de cette conception peut être affirmée que l'amitié demandée par Personne1 à Personne2 - si cette amitié est acceptée, l'amitié est considérée comme réciproque.
Je ferais quelque chose de similaire à ce que vous avez, mais retirez le drapeau "IsMutual". Ajoutez simplement une seconde ligne avec des valeurs inverses quand c'est mutuel. Il ajoute des lignes, mais se sent beaucoup plus propre.
Que penses-tu de ma solution?
Vous avez 3 tables
1 **the user** (id,.etc)
2 **friend_request**(id,flaggerID,flaggedID)
3 **friend**(id,frienderID,friendedID)
Vous vous connectez, vérifiez si je suis dans la table des amis, si oui, listez vos amis (je suis dans friender> liste friended) (je suis dans friended> listfriender)
Est-ce que j'ai une demande? (Suis-je en flaggedID?) Le connaissez-vous? Sinon, supprimez l'enregistrement. Si c'est le cas, créez un nouveau dossier à la demande lorsque je me mets dans le générateur de drapeaux et que le signaleur est activé. Nous avons maintenant une mutualité entre 2 enregistrements dans la table des requêtes, nous les supprimons donc et les plaçons dans la table des amis . Facile à séparer req/amis.
Peut-être ajouter une table de relation, y placer les propriétés de relation et la référencer depuis UserFriend.
Probablement au-dessus, mais on peut utiliser le Web sémantique pour modéliser cela. On peut utiliser le format FOAF (ami d'un ami).
Je l'ai fait comme ça:
Utilisateur TABLE
id name
-----------
1 foo
2 roo
3 shoo
4 mooo
TABLE relation d'amitié
id u_id f_id
--------------
1 1 2
2 2 1
3 3 1
4 1 3
Chaque fois qu'une demande d'ami est acceptée, insère la méthode inverse 1 2 & 2 1
et une requête simple:
$ufq=mysql_query("SELECT t1.f_id,t2.id,t2.name FROM friends AS t1, user AS t2 WHERE t1.u_id='$u_id' AND t2.id=t1.f_id ORDER BY t2.name ")or die(mysql_error());
while($fn=mysql_fetch_array($ufq)){
echo $fn["name"].'<br>';
}
Avez-vous réellement besoin d’une table physique pour savoir s’il ya des amis communs? Pourquoi ne pas faire une requête SQL comme:
SELECT U.ID, U.NAME FROM USER U
INNER JOIN USERFRIEND UF
ON U.ID = UF.FRIENDID
WHERE U.ID = (SELECT USER.ID FROM USER
WHERE USER.ID = friend_id AND USER.ID != your_id);
Les résultats de la requête doivent renvoyer tous les amis communs.
Les amitiés sont moins évidentes que les scénarios classiques d’employeur/patron et d’utilisateur/conjoint. L'amitié est-elle une relation ou une activité? J'ai reçu pas mal de critiques pour avoir négligé ces derniers. Quoi qu'il en soit, vous aurez probablement besoin de plusieurs tables, quel que soit le caractère générique de votre modèle de données.
Eh bien, je suis en retard à la fête, mais voici ma candidature.
D'abord les tables:
User
-id
Type
-id
Relationship
-user_id_1
-user_id_2
-type_id
Maintenant, je veux garder ma table de type simple. Ainsi, les types que j’ajoute ne représentent que la relation d’un utilisateur avec un autre. Ils ne représentent jamais la relation bidirectionnelle. Par exemple:
friend
ignored
Cela facilite l'ajout de nouveaux types. Je n'ai pas à penser ou créer toutes les combinaisons possibles de tous mes types. Je viens d'ajouter le nouveau type.
Pour créer une amitié, vous avez besoin de 2 entrées dans la table de relations. Si les deux utilisateurs conviennent qu'ils sont amis, ils le sont également. Si un seul dit qu'il est ami avec l'autre et que l'autre le fait bloquer, ils ne sont pas amis.
Faire des requêtes est très simple. Voici comment obtenir tous les amis de MySQL:
SELECT u.* FROM user u
LEFT JOIN relationship r1 ON u.id = r1.user_id_2
LEFT JOIN relationship r2 ON u.id = r2.user_id_1
WHERE r1.user_id_1 = <my_user_id> # my relationship with them
AND r1.type_id = <friend_type_id> # i say i'm a friend
AND r2.user_id_2 = <my_user_id> # their relationship with me
AND r2.type_id = <friend_type_id> # they say they're friends
Je pense aussi que cette approche est plus "transaction sûre". Imaginez que vous envoyez une demande d'ami à quelqu'un et que vous bloquez ensuite cette personne. Si cette personne accepte plus tard la demande d'ami, cela n'a pas d'importance. Cela ne change pas l'état de la relation, car elle est complètement indépendante.
Si vous aviez plutôt un seul type représentant la relation bidirectionnelle, vous seriez obligé de faire une sorte d'évaluation dans votre code, de ce que devrait être exactement le nouvel état de la relation, une fois que l'ami a accepté la demande d'ami. Sinon, vous pourriez débloquer un utilisateur et faire de cette personne des amis avec l'utilisateur qu'il avait bloqué.
Je préférerais de loin gérer cela au niveau de la base de données. Si un groupe de programmeurs travaillent sur l'application, il ne faut pas longtemps avant que quelqu'un oublie ce problème quelque part et un bogue difficile à trouver est créé.
D'après ce que j'ai compris, l'amitié est le résultat d'une relation entre deux utilisateurs (Utilisateur1 et Utilisateur2) et, du fait qu'un utilisateur1 peut avoir 0 utilisateur (s) ou plusieurs en tant qu'ami (s) et inversement utilisateur2, une table de jonction "Ami" Commes au milieu pour représenter cette relation comme ceci:
User1 id (int) nom d'utilisateur (chaîne)
User2 id (int) nom d'utilisateur (chaîne)
Ami ---- id (int) user1_Id (int) user2_Id (int) actif (bool)
User1_Id et user2_Id sont des FK dans la table Frind
J'espère que j'ai raison.
Je pense que vous devriez créer deux tables:
1. utilisateur
u_id int
u_nom_utilisateur chaîne
balahhh ............
2. relation amicale
fs_id int
mise en relation int
related_id int