2013-02-28 55 views
5

我不太確定如何對此進行表述,但是有沒有一種很好的方法來實現列在本質上可以互換的表?如何表示可互換列

示例:您有一個用戶模型,並且希望允許兩個用戶成爲'好友'。對我來說,顯而易見的方法是創建一個包含兩列('friend1'和'friend2')的表格,每個列都包含用戶的密鑰。由於你必須檢查「(friend1 = user1和friend2 = user2)或(friend1 = user2和friend2 = user1)」,這使得說「像user1和user2朋友」這樣的東西很尷尬。它會起作用,但對我來說,每當你想從該表中獲得某些東西時,你都會在兩欄中看到它,這似乎很尷尬。有沒有更優雅的方式做到這一點?

+0

對不起,我錯了 - 這將無法正常工作(查詢找到了友誼是錯誤的)。我會刪除我的答案。 – 2013-02-28 19:52:33

回答

3

建立友誼關係時的一個關鍵選擇是決定它是否是雙向的。 Twitter是一個雙向友好和Facebook友誼的例子。聽起來像你致力於雙向的,所以你有2個選項分別是:

1)檢查兩個方向

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

2)始終把降低USER_ID到朋友1和更高USER_ID成friend2,那麼你的測試只需要檢查一個方向。這是一個有點棘手的維護,所以我只會做它需要的全面原因。

+1

雙向友誼就是我所要做的,謝謝。即使第二個選項,雖然仍然會有一些尷尬的查詢(例如,列出你必須 user1的朋友'(從朋友 選擇朋友1 其中FRIEND2 = USER1) 工會 (從朋友 那裏朋友1選擇FRIEND2 = USER1)') – user1916823 2013-02-28 20:30:40

1

你可以實現這一點的方式看起來有點尷尬。這個想法是在一個有兩列的表中有一個「friendshipId」:friendshipId和user。現在用戶可以互換。

。如果user1和user2是朋友瞭解一下:

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 

明智地使用約束,觸發器和存儲過程將確保一個朋友關係只有兩個用戶,其他人無法朋友自己,所以上。

+0

這是在數據庫級別以最可能最真實的方式表示關係性質的好方法。事實上,在應用程序層使用幾個域和唯一的約束以及一個簡單的幫助函數,就可以完成這個任務,而不需要簡單的觸發器或繁瑣的sprocs。例如,您可以向朋友表添加一個位置列(> 0,<= 2,用'friendshipID'唯一)。要啓動,必要時手動插入數據仍然很簡單。不過,我可能會用self-join來查詢friends表,而不是'having'子句。 – WCWedin 2013-02-28 20:50:42

0

要如何鏈接您的用戶模型連接表你可以通過或的has_many has_and_belongs_to_many http://guides.rubyonrails.org/association_basics.html

任何。

例如

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 

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