我有一个模型House
,其中有许多布尔属性,例如has_fireplace
,has_basement
,has_garage
等等。这些布尔属性大约有30个左右。要使数据库存储和搜索效率更高,应该如何构建这个模型?
例如,我最终希望搜索所有具有壁炉和车库的House
。
我想单纯地在模型中添加30个布尔属性,每个属性对应数据库中的一列,但我想知道是否有Rails最佳实践,这点让我好奇。
我有一个模型House
,其中有许多布尔属性,例如has_fireplace
,has_basement
,has_garage
等等。这些布尔属性大约有30个左右。要使数据库存储和搜索效率更高,应该如何构建这个模型?
例如,我最终希望搜索所有具有壁炉和车库的House
。
我想单纯地在模型中添加30个布尔属性,每个属性对应数据库中的一列,但我想知道是否有Rails最佳实践,这点让我好奇。
如果一个模型有很多布尔值,建议使用单个整数和位运算来表示、存储和检索值。例如:
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)
我建议使用flag_shih_tzu gem。它可以帮助您将许多布尔属性存储在一个整数列中。它为每个属性提供了命名范围,并提供了一种将它们链接在一起作为活动记录关系的方法。
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
那么每个房屋的属性都将成为数据库条目。
不要忘记在您的数据库上设置联接表。
如果你想要查询这些属性,那么如果性能是一个考虑因素,很遗憾你可能只能使用一流的字段。位字段和标志字符串是解决问题的一种简单方式,但它们与生产数据集不可扩展。
如果你不担心性能问题,那么我建议采用一种实现方式,其中每个属性由一个字符代表(例如“a”=“车库”,“b”=“壁炉”等),并且你只需构建一个表示记录所有标志的字符串。这种方法相对于位字段的主要优点是:a)易于人类调试,b)你不需要担心数据类型的大小。
如果性能是一个问题,那么你可能需要将它们提升为一流的字段。
通常我会同意你的幼稚假设是正确的。
如果布尔字段的数量不断增长 (has_fusion_reactor?
),您也可以考虑序列化一个标志数组。
# 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"
我在考虑这样的东西
你有一个房屋表(用于存储房屋的详细信息)
你还有另一个主表,名为“特征”(其中包含诸如“壁炉”,“地下室”等功能)
然后你有一个连接表,名为Houses_Features,它有house_id和feature_id
通过这种方式,您可以将功能分配给给定的房屋。不知道这是否符合您的需求,但请考虑一下:D
谢谢和问候
Sameera
data
),然后你的查询可以使用SQL的LIKE。LIKE '%"has_fireplace":true%'
进行查找将返回任何带有壁炉的内容。