【问题标题】:Querying jsonb array for partial value查询 jsonb 数组的部分值
【发布时间】:2019-01-09 10:10:35
【问题描述】:

在 Rails 5.2 应用程序中,User 模型具有 subscriptions jsonb 属性

t.jsonb "subscriptions", default: [], null: false

一个例子是

irb(main):091:0> User.first.subscriptions
=> [{"id"=>"dfdaad60", "type"=>"Organization"}, 
    {"id"=>"18616f4d", "type"=>"Project"}]

我怎样才能使用 arel 获得所有 subscriptions 中的 ids,其中 type 等于 Project

我尝试使用@> 运算符但没有成功。

【问题讨论】:

    标签: ruby-on-rails arel


    【解决方案1】:

    以下将返回 ids 的数组,用于用户的订阅(类型为“项目”),

    User.pluck(:subscriptions).flatten.map { |x| x['id'] if x['type'] == 'Project' }.compact
    

    您不需要 where AR 或 AREL 查询,因为您只需要 ids 出现在订阅中,类型为“项目”并且可以按上述方式获取。

    【讨论】:

    • 我认为是[{ type: 'Project'}] 而不是{ type: 'Project'},因为它是一个对象数组。
    • 这很难扩展(想象一下对一百万用户的双地图操作)
    • 双地图?他需要从具有不同“类型”的选定订阅中过滤 id 所以也需要在里面过滤。
    • 你的 pluck 之前是一张地图,因此是双地图。这可以通过单个 SQL 查询来实现,我会发布答案
    • @VincentRolea 是的,我添加了 pluck 可以提高性能。但是需要两个过滤器(pluck & map)
    【解决方案2】:

    这可以解决问题,使用自定义 SQL 语句:

    sql = "SELECT value->'id' AS id FROM users, jsonb_array_elements(users.subscriptions) WHERE data @> '#{[{type: "Project"}].to_json}'"
    result = ActiveRecord::Base.connection.execute(sql)
    puts result.to_a
    

    【讨论】:

    • 我需要 ActiveRecord::Relation 因为结果需要与 where 子句链接。谢谢。
    【解决方案3】:

    您可以使用ActiveRecordExtended gem 查找所有订阅项目类型的用户:

    User.where.contains(subscriptions: { type: "Project" })
    

    然后我会在 ruby​​ 中获取 id。

    【讨论】:

      猜你喜欢
      • 2020-05-22
      • 2019-07-02
      • 2022-01-22
      • 1970-01-01
      • 2015-11-28
      • 2021-01-29
      • 2022-01-11
      • 2018-06-16
      • 1970-01-01
      相关资源
      最近更新 更多