2013-02-28 14 views
5

Nie jestem pewien, jak to sformułować, ale czy istnieje dobry sposób na wdrożenie tabeli, w której kolumny są zasadniczo wymienne?Jak reprezentować wymienne kolumny

Przykład: masz model Użytkownicy i chcesz zezwolić dwóm Użytkownikom na "przyjaciół". Oczywistym dla mnie sposobem byłoby posiadanie tabeli zawierającej dwie kolumny ("friend1" i "friend2"), z których każda zawiera klucz do użytkownika. To sprawia, że ​​trudno powiedzieć coś w stylu "są user1 i user2 friends", ponieważ musisz sprawdzić "(friend1 = user1 AND friend2 = user2) OR (friend1 = user2 AND friend2 = user1)". To zadziałałoby, ale wydaje mi się niezręczne, że za każdym razem, gdy chcesz coś z tego stołu, przeglądasz w obu kolumnach. Czy jest to bardziej elegancki sposób?

+0

przykro mi, że się mylę - to nie będzie działać dobrze (kwerendy, aby znaleźć przyjaźń jest źle). Usuwam moją odpowiedź. –

Odpowiedz

3

Kluczowym wyborem podczas nawiązywania relacji przyjaźni jest podejmowanie decyzji, czy jest dwukierunkowy. Twitter, który jest przykładem jednokierunkowej przyjaźni i przyjaźni na Facebooku, które są dwukierunkowe. Brzmi jak jesteś zobowiązana do dwukierunkowy, więc 2 opcje masz to:

1) Sprawdzić obu kierunkach

select * 
from friendships 
where (friend1 = 123 and friend2 = 456) OR (friend2 = 123 and friend1 = 456) 

2) Zawsze umieścić dolną user_id do friend1 i wyższą user_id do friend2, wtedy twój test musi tylko sprawdzić jeden kierunek. Jest to nieco trudniejsze w utrzymaniu, więc zrobiłem to tylko z powodów związanych z perfekcją.

+1

Dwukierunkowa przyjaźń jest tym, do czego dążyłem, dziękuję. Nawet z drugiej opcji choć nadal będzie pewne niewygodne pytania (np. Do listy przyjaciół user1 za musisz '(wybierz friend1 z przyjaciółmi gdzie friend2 = user1) unia (wybierz friend2 z przyjaciółmi gdzie friend1 = user1) ') – user1916823

1

Sposób, w jaki można to zaimplementować, może wydawać się nieco niezręczny. Chodzi o to, aby w "friendId" umieścić tabelę z dwiema kolumnami: friendshipId i user. Teraz użytkownicy są wymienni.

Aby dowiedzieć się, czy user1 i user2 są przyjaciółmi:

select friendshipId 
from friends 
group by friendshipId 
having sum(case when name = user1 then 1 else 0 end) > 0 and 
     sum(case when name = user2 then 1 else 0 end) > 0 

rozsądnego korzystania z ograniczeń, wyzwalaczy i procedur przechowywanych zapewni, że związek przyjaciel ma tylko dwóch użytkowników, że ktoś nie może przyjaciel sami, a więc na.

+0

To dobry sposób na przedstawienie natury relacji w możliwie najbardziej dosłowny sposób na poziomie bazy danych. W rzeczywistości, z kilkoma domenami i unikalnymi ograniczeniami oraz prostą funkcją pomocniczą w warstwie aplikacji, można to zrobić bez gwałtownych wyzwoleń lub niewygodnych sprocsów. Na przykład, możesz dodać kolumnę 'Pozycja' do tabeli przyjaciół (> 0, <= 2, unikalne z' friendID'). Aby uruchomić, nadal byłoby banalnie wstawiać dane ręcznie, jeśli to konieczne. Najprawdopodobniej raczej zapytałbym o stół znajomych za pomocą samołączenia niż o klauzuli "posiadającej". – WCWedin

0

Można to zrobić poprzez has_many lub has_and_belongs_to_many http://guides.rubyonrails.org/association_basics.html

jakikolwiek sposób chcesz dołączyć tabelę, która łączy swoje modele użytkowników.

np

class User < ActiveRecord::Base 
    has_many :followings 
    has_many :followers, :through => :followings, :class_name => "User" 
    has_many :followees, :through => :followings, :class_name => "User" 
end 


class Following < ActiveRecord::Base 
    # fields: follower_id followee_id (person being followed) 
    belongs_to :follower, :class_name => "User" 
    belongs_to :followee, :class_name => "User" 
end 

sam jak user has many :users, or must I use another way for a friend based social network?

Powiązane problemy