2016-09-16 28 views
0

我有一个模型将数组存储在名为'attributes'的表列之一中。因此,3个独立的记录可能是这样的:Rails 4使用Ruby Enumerable使用数组查询数组

记录1

MyModel.attributes = {Red, Furry, Stinky} 

记录2

MyModel.attributes = {Red} 

记录3

MyModel.attributes = nil 

记录4

MyModel.attributes = {Blue, Furry, Sweet} 

我想查询该阵列,用于任何其他阵列,包括零的。结果应返回查询数组中具有任何属性的记录以及属性列为零的任何记录。

query_array = [Blue, Furry] 

这个问题的答案查询应提供记录1,记录3和记录4 - 再次,它不看的所有

目前,我可以,如果我只是查询

MyModel.all.select {|m| m.attributes["Furry"] or m.attributes["Blue"] } 
做到这一点

但我希望能够动态地创建数组,而不是手动编写m.attributes [“attribute”]。我不知道如何做到这一点,而不需要所有的数组项,我只想要任何数组项和没有属性的记录。

+0

你正在使用什么类型的数据库?该列是什么格式? –

回答

1

您可能不应该调用列attributes,因为此名称已用于rails模型中的属性哈希访问器。对于低于我的例子改名这tags

一个简单的解决办法是检查nil(总是包括这些记录),并检查标签的交叉点中有任何标签:

model_1.tags # => ['red', 'furry', 'stinky'] 
model_2.tags # => ['red'] 
model_3.tags # => nil 
model_4.tags # => ['blue', 'furry', 'stinky'] 

search_tags = ['red', 'blue'] 
MyModel.all.select do |model| 
    model.tags.nil? || (model.tags & search_tags).any? 
end 

你可以也写它作为一个嵌套循环:

search_tags = ['red', 'blue'] 
MyModel.all.select do |model| 
    model.tags.nil? || model.tags.any? { |tag| search_tags.include?(tag) } 
end 

这一切都在内存中完成,在红宝石本身。如果您有100_000或1_000_000记录,则所有这些记录都从数据库中提取,实例化并过滤。

因此,根据您的具体要求和您使用的数据库,您可以找到更简单/更高性能的解决方案。一些想法:

  • 商店标签在单独的表
  • 商店标签为逗号分隔字符串,并使用“喜欢”查询
  • 对Postgres JSON数据类型和查询功能Postgres提供
+0

谢谢......它实际上不叫属性,但名称让人分心,所以我添加了一个占位符名称。不过谢谢你的提醒。关于如何更好地做到这一点的建议....你是对的,这就像标签。我正在重构... – NothingToSeeHere

-1

你可以试试这个

query_array = [Furry, Blue] 
query_string = query_array.map{|query| "m.attributes[#{query}]" }.join(" || ") 

#=> "m.attributes[Furry] || m.attributes[Blue]" 

MyModel.all.select {|m| eval(query_string) } 

现在,所有你需要做的就是添加更多项目进入query_array

+0

请永远不要使用'eval'。这是邪恶的,危险的,难以调试,难以理解。 –

+0

忘记添加:并可以发布安全问题。 –