動態現場實施取決於以下幾個因素:
- 能夠動態地添加屬性
- 能夠支持新的數據類型
- 能力來獲取動態屬性,無需額外的查詢
- 能力訪問像常規屬性那樣的動態屬性
- 能夠根據動態屬性查詢對象。 (例如:找到具有 滑雪愛好的用戶)
通常情況下,解決方案不能滿足所有要求。 Mike的解決方案優雅地解決了1和5。你應該使用他的解決方案,如果你對你很重要。
這是一個長期的解決方案,可以滿足1,2,3,4和5
更新users
表
添加text
場叫meta
到用戶表。
更新您的User
模式
class User < ActiveRecord::Base
serialize :meta, Hash
def after_initialize
self.meta ||= {} if new_record?
end
end
添加新的元場
u = User.first
u.meta[:hobbies] = "skiing"
u.save
訪問元場
puts "hobbies=#{u.meta[:hobbies]}"
迭代元字段
u.meta.each do |k, v|
puts "#{k}=#{v}"
end
爲了解決您需要使用Solr的還是獅身人面像的全文搜索引擎,第5的要求。它們比依賴於LIKE
查詢的DB更有效率。
如果您通過太陽黑子寶石使用Solr,以下是一種方法。
class User
searchable do
integer(:user_id, :using => :id)
meta.each do |key, value|
t = solr_type(value)
send(t, key.to_sym) {value} if t
end
end
def solr_type(value)
return nil if value.nil?
return :integer if value.is_a?(Fixnum)
return :float if value.is_a?(Float)
return :string if value.is_a?(String)
return :date if value.is_a?(Date)
return :time if value.is_a?(Time)
end
def similar_users(*args)
keys = args.empty? ? meta.keys : [args].flatten.compact
User.search do
without(:user_id, id)
any_of do
keys.each do |key|
value = meta[key]
with(key, value) if value
end
and
end
end
end
仰望相似的用戶
u = User.first
u.similar_users # matching any one of the meta fields
u.similar_users :hobbies # with matching hobbies
u.similar_users :hobbies, :city # with matching hobbies or the same city
的性能增益這裏是顯著。
這聽起來像是一個非常好的解決方案。謝謝! – Andrew 2011-03-17 21:25:13