代码之家  ›  专栏  ›  技术社区  ›  NothingToSeeHere

Rails 4使用Ruby Enumerable使用数组查询数组

  •  0
  • NothingToSeeHere  · 技术社区  · 10 年前

    我有一个模型,它将数组存储在名为“attributes”的表列中。因此,3个单独的记录可能如下所示:

    记录1

      MyModel.attributes = {Red, Furry, Stinky}
    

    记录2

      MyModel.attributes = {Red}
    

    记录3

      MyModel.attributes = nil
    

    记录4

      MyModel.attributes = {Blue, Furry, Sweet}
    

    我想在这个数组中查询其他数组,包括nil。结果应返回查询数组中具有任何属性的任何记录以及属性列为nil的任何记录。

    query_array = [Blue, Furry] 
    

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

    MyModel.all.select {|m|   m.attributes["Furry"] or m.attributes["Blue"] }
    

    但我希望能够动态创建数组,而不是手动编码m.attributes[“attribute”]。在不需要所有数组项的情况下,我无法完全理解如何做到这一点,我只需要任何没有属性的数组项和记录。

    2 回复  |  直到 10 年前
        1
  •  1
  •   Pascal    10 年前

    您可能不应该调用该列 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
    

    这一切都是在内存中完成的,都是在ruby本身中完成的。如果您有100_000或1_000_000条记录,那么所有记录都将从数据库中提取,实例化,然后过滤。

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

    • 将标签存储在单独的表中
    • 将标记存储为逗号分隔的字符串并使用“like”查询
    • 使用postgresJSON数据类型和postgres提供的查询功能
        2
  •  -1
  •   davidhu    10 年前

    你可以试试这个

    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 .