我有一个模型House
,它有许多布尔属性,例如has_fireplace
,has_basement
,has_garage
等等。 House
有大约30个这样的布尔属性。构建此模型以实现高效数据库存储和搜索的最佳方法是什么?
我想最终搜索所有有壁炉和车库的Houses
。
我想,天真的方法是在模型中添加30个布尔属性,每个属性对应一个数据库中的一列,但我很好奇是否有一个我不知道的Rails最佳实践。
答案 0 :(得分:16)
您的'天真'假设是正确的 - 从查询速度和生产力角度来看,最有效的方法是为每个标志添加一列。
你可能会像其他人所描述的那样获得幻想,但除非你解决一些非常具体的性能问题,否则不值得付出努力。你最终会得到一个难以维护,灵活性降低且开发时间更长的系统。
答案 1 :(得分:7)
对于单个模型中的许多布尔值,您可以考虑使用单个整数和按位运算来表示,存储和检索值。例如:
class Model < ActveRecord::Base
HAS_FIREPLACE = (1 << 0)
HAS_BASEMENT = (1 << 1)
HAS_GARAGE = (1 << 2)
...
end
然后,一些名为flags
的模型属性将设置如下:
flags |= HAS_FIREPLACE
flags |= (HAS_BASEMENT | HAS_GARAGE)
并进行了如下测试:
flags & HAS_FIREPLACE
flags & (HAS_BASEMENT | HAS_GARAGE)
你可以抽象成方法。应该在时间和空间上非常有效地作为实现
答案 2 :(得分:5)
我建议the flag_shih_tzu gem。它可以帮助您在一个整数列中存储许多布尔属性。它为每个属性提供了命名范围,并将它们链接在一起作为活动记录关系。
答案 3 :(得分:4)
这是另一种解决方案。
您可以制作HouseAttributes
模型并设置双向has_and_belongs_to_many关联
# house.rb
class House
has_and_belongs_to_many :house_attributes
end
# house_attribute.rb
class HouseAttribute
has_and_belongs_to_many :houses
end
然后房子的每个属性都是数据库条目。
不要忘记在数据库上设置连接表。
答案 4 :(得分:3)
如果您想要查询这些属性,那么很遗憾,如果考虑性能,您可能会遇到一流的字段。位域和标志字符串是解决问题的简单方法,但它们不能很好地适应生产数据集。
如果你不打算担心性能,那么我会使用一个实现,其中每个属性由一个字符(“a”=“车库”,“b”=“壁炉”等)表示,并且你只需要构建一个表示记录所有标志的字符串。这比bitfield的主要优点是:a)人类更容易调试,b)你不必担心数据类型的大小。
如果表现是一个问题,那么你可能需要将它们推广到一流的领域。
答案 5 :(得分:2)
通常我同意你天真的假设是正确的。
如果布尔字段的数量不断增长和增长(has_fusion_reactor?
),您也可以考虑serializing一个标志数组
# house.rb
class House
serialize :flags
…
end
# Setting flags
@house.flags = [:fireplace, :pool, :doghouse]
# Appending
@house.flags << :sauna
#Querying
@house.flags.has_key? :porch
#Searching
House.where "flags LIKE ?", "pool"
答案 6 :(得分:1)
我正在考虑这样的事情
你有一张房子表(有关房子的详细信息)
你有另一个名为Features的主表(它具有'壁炉','地下室'等功能。)
你有一个像Houses_Features这样的连接表 它有house_id和feature_id
通过这种方式,您可以为给定的房屋分配功能。不知道这是否符合你的需要,但只要想一想:D
感谢和问候
sameera
答案 7 :(得分:0)
你总是可以拥有一个包含JSON的TEXT列(比如data
),然后你的查询可以使用SQL的LIKE。
例如:house.data#=&gt; '{ “has_fireplace”:真 “has_basement”:假 “has_garage”:真}'
因此,使用LIKE '%"has_fireplace":true%'
进行查找会返回任何带壁炉的内容。
在这种情况下,使用模型关系(例如,除了House之外的Fireplace,Basement和Garage的模型)会非常麻烦,因为你有这么多模型。