【问题标题】:Find records where length of array equal to - Rails 4查找数组长度等于的记录 - Rails 4
【发布时间】:2017-04-01 15:34:56
【问题描述】:

在我的Room 模型中,我有一个名为available_days 的属性,它被存储为一个数组。

例如:

Room.first.available_days
=> ["wed", "thurs", "fri"]

找到数组大小等于 3 的所有房间的最佳方法是什么?

我尝试过类似的东西

Room.where('LENGTH(available_days) = ?', 3)

没有成功。

更新:available_days 的数据类型是字符串,但为了存储数组,我正在序列化模型中的属性:

app/models/room.rb

serialize  :available_days

【问题讨论】:

  • 你能改变架构吗?使用serialize 几乎总是一个可怕的错误,一开始很快很容易,然后在你的脸上炸毁。

标签: sql ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

想不出一个纯粹的sqlsqlite 做这件事的方式,因为available_daysstring

但这是一种无需一次加载所有记录的方法。

rooms = []
Room.in_batches(of: 10).each_record do |r|
  rooms << r if r.available_days.length == 3
end

p rooms

【讨论】:

  • 感谢您的帮助。获取异常:no such function: cardinality@Rashmirathi
  • @Kathan 你用的是什么数据库?我假设您使用的是 postgres。还有available_days的数据类型是什么?
  • 用于开发的Sqlite3。 available_days 是一个字符串,但是,我将它序列化以存储一个数组。 @Rashmirathi
  • @Kathan 哦对不起,我的回答只适用于 postgres。如果您没有太多记录,您可以执行 Room.all.find { |room| room.avalibale_days.length == 3 } 之类的操作
  • @Kathan 另外,你是如何序列化 available_days 的?可以发一下代码吗?
【解决方案2】:

如果您使用的是 postgres,您可以将序列化的字符串解析为数组类型,然后查询数组的长度。我希望其他数据库可能有类似的方法。如何做到这一点取决于文本的序列化方式,但默认情况下 Rails 4 应该是 YAML,所以我希望你的数据编码如下:

---
- first
- second

以下 SQL 将删除前导 ---\n- 以及最后的换行符,然后将 - 上的剩余字符串拆分为一个数组。清理多余的字符以查找长度并不是绝对必要的,但是如果您想做其他操作,您可能会发现清理数组很有用(没有前导字符或尾随换行符)。这仅适用于简单的 YAML 数组和简单的字符串。

Room.where("ARRAY_LENGTH(STRING_TO_ARRAY(RTRIM(REPLACE(available_days,'---\n- ',''),'\n'), '\n- '), 1) = ?", 3)

如您所见,这种方法相当复杂。如果可能,您可能希望添加一个新的结构化列(数组或 jsonb)并将序列化的字符串迁移到一个类型化的列中,以使其更容易和更高效。 Rails 支持jsonb serialization for postgres

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-12
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    相关资源
    最近更新 更多