ActiveRecord Rails 4,如何查看数组属性是否包含数组中的任何值

gar*_*aro 3 postgresql activerecord ruby-on-rails-4

假设我有一个 Book 模型,它有一个类别属性,它是一个数组。我想创建一个范围,在其中我可以从我想要传入的另一个数组中获取至少包含一个项目的所有书籍。

经过广泛的谷歌搜索并尝试了许多不同的查询后,我发现的最接近的是:

Book.where("'Mystery' = ANY(categories)")
Run Code Online (Sandbox Code Playgroud)

如何将“Mystery”替换为类似的内容,['Categ1', 'Categ2', etc...]以便我可以检索包含数组中至少一个值的任何书籍?

mu *_*ort 5

您需要了解三件事:

  1. PostgreSQL 的数组重叠运算符:&&。array1 && array2如果两个数组有任何共同元素,则为 true。
  2. PostgreSQL 的数组构造函数语法,即array[v1, v2, v3]。
  3. 如果占位符的值是 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)
Run Code Online (Sandbox Code Playgroud)

你的范围是这样的:

scope :with_any_categories, ->(cats) { where('categories && array[?]', cats) }
Run Code Online (Sandbox Code Playgroud)

也许:

scope :with_any_categories, ->(*cats) { where('categories && array[?]', cats.flatten) }
Run Code Online (Sandbox Code Playgroud)

取决于您想如何使用范围。