假设我有一个 Book 模型,它有一个类别属性,它是一个数组。 我想创建一个范围,我可以从要传入的另一个数组中获取至少包含一个项目的所有书籍。
在谷歌上广泛搜索并尝试了许多不同的查询之后,我发现的最接近的是:
Book.where("'Mystery' = ANY(categories)")
如何将"神秘"替换为类似于['Categ1', 'Categ2', etc...]
的内容,以便我可以检索任何包含数组中至少一个值的书籍?
你需要知道三件事:
- PostgreSQL的数组重叠运算符:
&&
。 如果两个数组有任何共同的元素,则array1 && array2
为 true。 - PostgreSQL的数组构造函数语法,即
array[v1, v2, v3]
. - 如果占位符的值是 Ruby 数组,则 ActiveRecord 会将
?
占位符替换为逗号分隔的列表,以便where('c = any(array[?])', [1,2,3])
到达数据库时看起来像c = any(array[1,2,3])
。
如果你把所有这些放在一起,你会得到这样的东西:
categories = %w[Categ1 Categ2 Categ3]
Book.where('categories && array[?]', categories)
您的范围将是这样的:
scope :with_any_categories, ->(cats) { where('categories && array[?]', cats) }
或者也许:
scope :with_any_categories, ->(*cats) { where('categories && array[?]', cats.flatten) }
具体取决于您希望如何使用范围。