Como criar uma tabela de banco de dados de relacionamento para armazenar o relacionamento de amizade?


9

Quero criar uma tabela para armazenar o relacionamento de amizade no meu projeto da web

Deve satisfazer pelo menos as quatro condições a seguir:

que enviam a solicitação de adição de amigo, por exemplo (se A TO B, esta coluna será A)

que recebem a solicitação de adição de amigo, por exemplo (se A TO B, esta coluna será B)

status atual, por exemplo (0 indica rejeitado enquanto 1 indica aceito ou 2 indica não processado

nosso relacionamento de amizade é bilateral

Se algum de vocês tiver experiência com isso, qualquer sugestão será bem-vinda

meu design atual (acho ruim agora) é assim, essas são as colunas

frienshipId  
fromUserId  
toUserId  
status  
requestTime

Posso sugerir o uso da visualização de código (realce seu texto e pressione ctrl-k ou coloque quatro espaços antes de cada linha) e destaque seu DDL para que possamos ver como seu modelo de dados foi projetado (ou como você deseja projetá-lo)
jcolebrand

Verifique também a discussão aqui: stackoverflow.com/questions/10807900/…
Flo

Use um banco de dados gráfico. Eles foram projetados exatamente para essas circunstâncias.
Michael Green

Respostas:


9

Eu criaria uma tabela muito parecida com a sua. Estou usando tipos de dados e sintaxe do SQL Server, talvez seja necessário ajustar dependendo da sua plataforma.

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

A indexação da tabela será crítica à medida que a tabela cresce para dezenas e centenas de milhões.


E quanto a um índice / chave primária em cluster no StatusId?
11111 bernd_k

Corrigido o problema de nome duplicado. O índice de cluster deve estar no FriendStatusId. A chave primária pode ser FriendStatusId ou uma combinação de FromUserId e ToUserId.
mrdenny

Embora se você permitir várias solicitações de amizade, deseje a PK no FromUserID, ToUserId, SentTime ou no Clustered Index.
mrdenny

a sua estratégia de nomeação é melhor ...
Hi福气鱼

8

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

Para listar amizades, uma visão:

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;

Você pode usá-lo assim:

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

O que faz você pensar que seu design atual é ruim? Aqui está uma tabela de criação para 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;

Se o banco de dados for Oracle, convém considerar uma coluna virtual indexada que limitará os dados às entradas necessárias para consultas específicas. Por exemplo, você pode ter uma coluna virtual chamada AcceptedFromUserId que usa a função DECODE (StatusId, 1, FromUserId, NULL). O índice conteria apenas AcceptedUserIds e, portanto, seria menor que um índice para todos os UserIds. Se você limpar regularmente solicitações rejeitadas, uma coluna virtual indexada em PendingToUserId poderá ser mais útil.

Uma alternativa se você tivesse particionamento seria particionar a tabela no StatusId.

Se você não precisar de várias solicitações de amizade entre os mesmos usuários ao mesmo tempo, poderá abandonar o FriendId usando FromUserId, ToUserId e StatusId como sua chave principal. Nesse caso, você também deve considerar tornar a tabela uma tabela organizada por índices.


-2

Esquema:

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
)

Do PHP:

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

E o que fazer com a mutualidade? (E a friendsdefinição da tabela é suspeito de erro de sintaxe.)
Dezso
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.