创建活动记录范围以在 Jsonb 字段上排序

Dav*_*mar 2 activerecord ruby-on-rails sql-order-by jsonb

我有一个名为 session 的表,其中包含一个名为 lms_data 的 jsonb 属性。我想创建一个范围以按 jsonb 列中的特定字段进行排序。以下查询运行良好select * from sessions ORDER BY lms_data->>'startDate' ASC ,但是会话模型中的以下范围不会执行:

  scope :order_by_start_date_asc, -> { order("lms_data->>'startDate' ASC ") }
Run Code Online (Sandbox Code Playgroud)

它失败了Query method called with non-attribute argument(s): "lms_data->>'startDate' ASC "

如何创建基于 jsonb 列中的字段进行排序的范围?

eng*_*nky 6

从 Rails 6 开始,原始 SQL 被禁止使用,并将order其称为“危险的查询方法”;然而,弃用警告还提供了“可以通过将已知安全值包装起来来传递它们”,因此我们可以通过创建类似的内容Arel.sql()来解决您的错误Arel::SqlLiteral

scope :order_by_start_date_asc, -> { order(Arel.sql("lms_data->>'startDate'").asc) }
Run Code Online (Sandbox Code Playgroud)

我们可以将内部字符串转换为自己的节点,但这应该可以帮助您克服所讨论的障碍。

要将其转换为完整的,Arel您可以使用

order(
  Arel::Nodes::InfixOperation.new('->>',
    Arel.sql('lms_data'),
    Arel.sql("'start_date'")
).asc)
Run Code Online (Sandbox Code Playgroud)