【问题标题】:ActiveRecord Rails 4, how to look if array attribute contains any of values in arrayActiveRecord Rails 4,如何查看数组属性是否包含数组中的任何值
【发布时间】:2020-05-07 05:15:54
【问题描述】:

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

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

Book.where("'Mystery' = ANY(categories)")

如何将 'Mystery' 替换为 ['Categ1', 'Categ2', etc...] 之类的东西,以便我可以检索包含数组中至少一个值的任何 Book?

【问题讨论】:

    标签: postgresql ruby-on-rails-4 activerecord


    【解决方案1】:

    你需要知道三件事:

    1. PostgreSQL 的数组重叠运算符:&&。如果两个数组有任何共同的元素,array1 && array2 为真。
    2. PostgreSQL 的array constructor syntax,即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)
    

    你的作用域是这样的:

    scope :with_any_categories, ->(cats) { where('categories && array[?]', cats) }
    

    或许:

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

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

    【讨论】:

    • 那行得通,这是一个很好的答案,我什至不知道如何寻找这些概念,谢谢!
    • 非常感谢。我只是在寻找这个,它不仅解决了我的问题,还帮助你掌握了 Rails/Postgres 的一些概念。
    • 我收到ActiveRecord::StatementInvalid (PG::UndefinedFunction: ERROR: operator does not exist: character varying[] && text[]
    • @Rob 您应该可以添加类型转换:where('categories::text[] && array[?]', ...)where('categories && array[]::varchar[]', ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    相关资源
    最近更新 更多