Wie entwerfe ich eine Beziehungsdatenbanktabelle zum Speichern einer Freundschaftsbeziehung?

9

Ich möchte eine Tabelle entwerfen, um die Freundschaftsbeziehung in meinem Webprojekt zu speichern

Es sollte mindestens die folgenden 4 Bedingungen erfüllen:

Wer sendet die Add-Friend-Anfrage, zB (wenn A bis B, dann ist diese Spalte A)

die die Add-Friend-Anfrage erhalten, z. B. (wenn A bis B, dann ist diese Spalte B)

aktueller Status zB (0 bedeutet abgelehnt, während 1 akzeptiert oder 2 unverarbeitet bedeutet

Unsere freundschaftliche Beziehung ist bilateral

Wenn einer von Ihnen damit vertraut ist, ist jeder Vorschlag willkommen

Mein aktuelles Design (ich denke im Moment schlecht) ist so, das sind die Spalten

frienshipId  
fromUserId  
toUserId  
status  
requestTime
Hallo 福气 鱼
quelle
Kann ich vorschlagen, die Codeansicht zu verwenden (markieren Sie Ihren Text und drücken Sie Strg-k oder setzen Sie vier Leerzeichen vor jede Zeile) und Ihre DDL hervorzuheben, damit wir sehen können, wie Ihr Datenmodell entworfen ist (oder wie Sie es entwerfen möchten)
jcolebrand
Überprüfen Sie auch die Diskussion hier: stackoverflow.com/questions/10807900/…
Flo
Verwenden Sie eine Diagrammdatenbank. Diese sind genau für diese Umstände ausgelegt.
Michael Green
quora.com/…
Vlady Veselinov

Antworten:

9

Ich würde eine Tabelle erstellen, die der von Ihnen sehr ähnlich ist. Ich verwende SQL Server-Datentypen und -Syntax. Je nach Plattform müssen Sie möglicherweise Anpassungen vornehmen.

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

Die Indizierung der Tabelle ist von entscheidender Bedeutung, wenn die Tabelle auf Dutzende und Hunderte von Millionen anwächst.

mrdenny
quelle
Was ist mit einem Clustered-Index / Primärschlüssel für StatusId?
Bernd_k
Das Problem mit dem doppelten Namen wurde behoben. Der Clustered-Index sollte sich auf der FriendStatusId befinden. Der Primärschlüssel kann FriendStatusId oder eine Kombination aus FromUserId und ToUserId sein.
Mrdenny
Wenn Sie jedoch mehrere Freundschaftsanforderungen zulassen, möchten Sie die PK für FromUserID, ToUserId, SentTime oder den Clustered Index.
Mrdenny
Ihre Namensstrategie ist besser ...
Hi 福气 鱼
8

Auf 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
)

Zum Auflisten von Freundschaften eine Ansicht:

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;

Sie können es so verwenden:

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
jkj
quelle
3

Was lässt Sie denken, dass Ihr aktuelles Design schlecht ist? Hier ist eine Tabelle zum Erstellen für 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;

Wenn es sich bei der Datenbank um Oracle handelt, sollten Sie eine indizierte virtuelle Spalte in Betracht ziehen, die die Daten auf Einträge beschränkt, die für bestimmte Abfragen erforderlich sind. Beispielsweise könnten Sie eine virtuelle Spalte mit dem Namen AcceptedFromUserId haben, die die Funktion DECODE (StatusId, 1, FromUserId, NULL) verwendet. Der Index würde nur AcceptedUserIds enthalten und wäre daher kleiner als ein Index für alle UserIds. Wenn Sie abgelehnte Anforderungen regelmäßig bereinigen, ist eine indizierte virtuelle Spalte in PendingToUserId möglicherweise nützlicher.

Eine Alternative, wenn Sie eine Partitionierung hätten, wäre die Partitionierung der Tabelle auf der StatusId.

Wenn Sie nicht mehrere Freundschaftsanfragen zwischen denselben Benutzern gleichzeitig benötigen, können Sie die FriendId mit FromUserId, ToUserId und StatusId als Primärschlüssel verlassen. In diesem Fall sollten Sie auch in Betracht ziehen, die Tabelle zu einer indexorganisierten Tabelle zu machen.

Leigh Riffel
quelle
-2

Schema:

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
)

Von PHP:

select * 
from friends 
where user_a=$myid or user_b=$myid
jiss
quelle
Und was tun mit Gegenseitigkeit? (Und die friendsTabellendefinition ist verdächtig für Syntaxfehler.)
Dekso