Olá pessoal, estou com uma pequena dúvida sobre como fazer um pequeno sistema que funcione como uma rede social.
Gostaria de saber qual seria um bom modelo de dados para Usuarios e Amigos. Pesquisei um pouco e vi que poderia fazer da seguinte forma:
[code]Tabela Usuario
ID_USER
TX_NOME
Tabela Amigos
ID_AMIZADE
ID_USER
ID_USER_AMIGO[/code]
Vamos supor que eu tenha o usuário “Roberto” e ele se torne amigo de “Antônio”
ID_USER TXNOME
1 ROBERTO
2 ANTÔNIO
--AMIZADE--
ID_AMIZADE ID_USER ID_USER_AMIGO
1 1 2
Isso significa que o usuário Roberto é amigo de Antônio, então creio que não preciso inserir outro registro para dizer que Antônio é amigo de Roberto. Certo?
ID_AMIZADE ID_USER ID_USER_AMIGO
1 1 2
2 2 1
Creio que o primeiro exemplo já basta. Porém como posso retornar os dados, sendo que o ID_USER é o que adicionou e o ID_USER_AMIGO é o adicionado.
Então assim ‘Roberto’ poderia estar em qualquer um dos dois campos dependendo do fato de ele ter adicionado alguém ou ter sido adicionado por alguém
Então a pergunta é, em uma instrução select como eu poderia verificar quais os amigos de “Roberto”? Sendo que ele possa estar em qualquer uma das duas colunas.
Ex:
ID_AMIZADE ID_USER ID_USER_AMIGO
1 1 2
2 3 1
Roberto adicionou Antônio e um suposto usuário 3 -Que eu sei que não existe- adicionou roberto então quero saber todos amigos de Roberto.
Parece simples, mas estou um pouco confuso, se alguém poder me ajudar ficarei muito agradecido.
Cara eu estou fazend algo parecido aqui para uma aplicação minha, depende muito da sua visão, acho que para ficar da forma como você montou seu banco, você vai ter que encarar que todos os que o usuário adciona devem aceitar o convite, e o que aceitam sáo automaticamente meus amigos e eu amigo deles.
Sendo assim você pode na hora da consulta trazer todos o ID_Amigos onde o ID_USUARIO apareça e trazer também todos os ID_USUARIOS onde meu ID apareça como ID_AMIGOS
seria mais ou menos isso
SELECT * FROM amizade WHERE ID_USER = 1 and ID_USER_AMIGO = 1 and APROVADO = 1
Dessa forma acho que vou ter todos os que eu add e todos os que me add e só os que estão aprovados.
se você quer mesmo armazenar as relações de amizade desta forma será necessario sim criar dois registros na tabela de amizades para cada nova amizade, pois esta é a melhor maneira de garantir que você está realmente pegando só os amigos do USER.
No entanto, existem outras formas de armazenar amigos, ja ví casos onde a tabela amigos era composta com um campo INT e um TEXT, onde o INT pegava o id do usuario e o TEXT ficava uma sequência de IDs de seus amigos separados por virgula. Assim, caso você tenha 10 mil usuarios sua tabela de amigos teria exatos 10 mil registros,
Utilizando sua forma, 10 mil usuarios com cada um tendo em média 100 amigos daria 1 milhão de registros.
Mas muitas coisas devem ser levadas em consideração, como por exemplo, se você quiser marcar a data em que a amizade entre duas pessoas começou não teria muita escolha a não ser fazer do jeito que você fez, porém, inserindo uma coluna para armazenar a data.
Bom, considerando tua lógica, um usuário pode adicionar muitos amigos e cada amigo pode adicionar vários usuários, certo?
Logo, a relação usuário x amigo é muitos para muitos.
Obrigatoriamente, esse tipo de relação requer uma tabela adicional, contendo a relação entre amigo e usuário.
Por que isso?
Bom, se eu te convido a ser meu amigo e você recusa, isso não me faz ser teu amigo, logo, não existe essa relação.
Assim sendo, se você tiver uma rede com 10 mil usuários, o máximo de amizades que cada usuário terá será de 9999 (ele não pode ser amigo dele mesmo).
sim, tem uma relação N:N aí. Porém, este caso de usuarios e amigos deve ser visto como exceção, já que não se trata de duas tabelas de dados interligadas entre sí indo-e-voltado para dois lados e sim de uma tabela de dados que vai-e-volta duas vezes para o mesmo lado.
É como se fossem na verdade dois 1:N na mesma direção.
A redudancia é real e garante a integridade da informação.
Uma terceira tabela poderia ser utilizada para guardar meta-dados sobre a amizade, mas ainda sim não eliminaria a redundancia da tabela de amigos.
[quote=leoap86]posso estar errado, mas a minha opinião é que:
sim, tem uma relação N:N aí. Porém, este caso de usuarios e amigos deve ser visto como exceção, já que não se trata de duas tabelas de dados interligadas entre sí indo-e-voltado para dois lados e sim de uma tabela de dados que vai-e-volta duas vezes para o mesmo lado.
É como se fossem na verdade dois 1:N na mesma direção.
A redudancia é real e garante a integridade da informação.
Uma terceira tabela poderia ser utilizada para guardar meta-dados sobre a amizade, mas ainda sim não eliminaria a redundancia da tabela de amigos.
[/quote]
Não enxergo esta redundância de maneira alguma, a não ser que consideremos a hipótese de, quando um usuário adicionar um amigo, tornar-se imediatamente amigo do mesmo, sem ao menos ser “aprovado”.
Porém, se considerarmos o modelo facebook (e orkut, por que não?), em que a amizade é estabelecida a partir da solicitação e confirmação pela outra parte, então não existe redundância, afinal, para buscar todos os amigos de A, faz-se um join, da mesma forma que para qualquer outro usuário ou amigo.
Esse modelo relacional não é o melhor pra representar uma rede social. Até porque permite que aconteçam bizarrices do tipo:
“A é amigo de B, mas B não é amigo de A”.
Isso não faz sentido algum. Se A pediu pra ser amigo de B e B aceitou, ambos são amigos.
Eu acredito que isso poderia ser melhor solucionado usando um outro modelo, de preferência de grafos não-direcionados, em que cada relacionamento é representado por uma aresta entre dois nós.
Eu nunca usei, mas sei que o Neo4J (http://neo4j.org/) é um banco NoSQL baseado em grafos, que, na minha opinião ficaria melhor.