Comment concevoir une table de base de données de relations pour stocker une relation d'amitié?


9

Je veux concevoir une table pour stocker la relation d'amitié dans mon projet web

Il doit satisfaire au moins aux 4 conditions suivantes:

qui envoie la demande d'ajout d'un ami, par exemple (si A TO B alors cette colonne sera A)

qui reçoivent la demande d'ajout d'un ami, par exemple (si A TO B alors cette colonne sera B)

état actuel, par exemple (0 signifie rejeté alors que 1 signifie accepté ou 2 signifie non traité

notre relation d'ami est bilatérale

Si vous êtes expérimenté dans ce domaine, toute suggestion est la bienvenue

ma conception actuelle (je pense que mal en ce moment) est comme ça ce sont les colonnes

frienshipId  
fromUserId  
toUserId  
status  
requestTime

Puis-je suggérer d'utiliser la vue de code (mettez votre texte en surbrillance et appuyez sur ctrl-k ou mettez quatre espaces avant chaque ligne) et mettez en surbrillance votre DDL afin que nous puissions voir comment votre modèle de données est conçu (ou comment vous voulez le concevoir)
jcolebrand

Consultez également la discussion ici: stackoverflow.com/questions/10807900/…
Flo

Utilisez une base de données graphique. Ceux-ci sont conçus pour ces circonstances.
Michael Green

Réponses:


9

Je créerais une table un peu comme celle que vous avez. J'utilise les types de données et la syntaxe de SQL Server, vous devrez peut-être modifier en fonction de votre plate-forme.

CREATE TABLE FriendStatus
(FriendStatusId BIGINT PRIMARY KEY IDENTITY(1,1),
FromUserId BIGINT,
ToUserId BIGINT,
StatusId TINYINT,
SentTime DATETIME2,
ResponseTime DATETIME2);

L'indexation de la table sera critique à mesure que la table atteint des dizaines et des centaines de millions.


Qu'en est-il d'un index cluster / clé primaire sur StatusId?
bernd_k

Correction du problème de nom en double. L'index cluster doit être sur le FriendStatusId. La clé primaire peut être FriendStatusId ou une combinaison de FromUserId et ToUserId.
mrdenny

Bien que si vous autorisez plusieurs demandes d'amis, vous souhaiterez le PK sur FromUserID, ToUserId, SentTime ou l'index clusterisé.
mrdenny

votre stratégie de nommage est meilleure ...
Salut 福气 鱼

8

Sur PostgreSQL:

CREATE TABLE users (
    users_id serial PRIMARY KEY,
    name text UNIQUE NOT NULL
);

CREATE TABLE friends (
    friends_id serial PRIMARY KEY,
    timestamp TIMESTAMPTZ default now(),
    user_a integer NOT NULL REFERENCES users,
    user_b integer NOT NULL REFERENCES users,
    status integer NOT NULL default 2
)

Pour lister les amitiés, une vue:

CREATE VIEW friendships AS
    SELECT DISTINCT user_a, user_b FROM friends WHERE status = 1
    UNION
    SELECT DISTINCT user_b, user_a FROM friends WHERE status = 1;

Vous pouvez l'utiliser comme ceci:

INSERT INTO users ( name ) VALUES ( 'foo' );
INSERT INTO users ( name ) VALUES ( 'bar' );
INSERT INTO users ( name ) VALUES ( 'baz' );

SELECT * FROM users;
 users_id | name 
----------+------
        1 | foo
        2 | bar
        3 | baz

INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 1, 2, 1 );
INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 2, 1, 1 );
INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 1, 3, 1 );

SELECT * FROM friendships ORDER BY user_a, user_b;
 user_a | user_b 
--------+--------
      1 |      2
      1 |      3
      2 |      1
      3 |      1

SELECT a.name, b.name
    FROM friendships
    JOIN users a ON a.users_id = user_a
    JOIN users b ON b.users_id = user_b
    ORDER BY a.name, b.name;
 name | name 
------+------
 bar  | foo
 baz  | foo
 foo  | bar
 foo  | baz

3

Qu'est-ce qui vous fait penser que votre design actuel est mauvais? Voici une table de création pour Oracle:

CREATE TABLE IVR.FRIEND (
     FRIENDID   NUMBER(7) NOT NULL 
   , FROMUSERID NUMBER(7) NOT NULL 
   , TOUSERID   NUMBER(7) NOT NULL 
   , STATUSID   NUMBER(2) NOT NULL
   , REQUESTED  DATE      NOT NULL 
   , CONSTRAINT FRIEND_PK PRIMARY KEY (FRIENDID) ENABLE 
);
CREATE SEQUENCE FRIENDIDSEQ;

Si la base de données est Oracle, vous pouvez envisager une colonne virtuelle indexée qui limitera les données aux entrées nécessaires pour des requêtes particulières. Par exemple, vous pouvez avoir une colonne virtuelle appelée AcceptedFromUserId qui utilise la fonction DECODE (StatusId, 1, FromUserId, NULL). L'index ne contiendrait que AcceptedUserIds et serait donc plus petit qu'un index pour tous les UserIds. Si vous nettoyez régulièrement les demandes rejetées, une colonne virtuelle indexée sur PendingToUserId pourrait être plus utile.

Une alternative si vous aviez un partitionnement serait de partitionner la table sur le StatusId.

Si vous n'avez pas besoin de plusieurs demandes d'amis entre les mêmes utilisateurs en même temps, vous pouvez abandonner FriendId en utilisant FromUserId, ToUserId et StatusId comme clé primaire. Dans ce cas, vous devez également envisager de faire de la table une table organisée par index.


-2

Schéma:

CREATE TABLE users (
    users_id serial PRIMARY KEY,
    name text UNIQUE NOT NULL
);

CREATE TABLE friends (
    friends_id serial PRIMARY KEY,
    timestamp TIMESTAMPTZ default now(),
    user_a integer NOT NULL REFERENCES users,
    user_b integer NOT NULL REFERENCES users,
    status integer NOT NULL default 2
)

Depuis PHP:

select * 
from friends 
where user_a=$myid or user_b=$myid

Et que faire de la mutualité? (Et la friendsdéfinition de la table est suspecte d'erreur de syntaxe.)
dezso
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.