【问题标题】:Activerecord Query postgres jsonb array for integer memberActiverecord查询整数成员的postgres jsonb数组
【发布时间】:2021-09-28 15:48:34
【问题描述】:

我有一个带有 jsonb 列的下表配置文件

item_type object_changes
"Item" [{"customer_id": [1, 5], "other_id": 1}, {"customer_id": [4, 5], "other_id": 2}]
"Item" [{"customer_id": [3, 6], "other_id": 3}, {"customer_id": [3, 5], "other_id": 2}]

我希望能够使用活动记录查询以查找所有 customer_id 为 5 的行。

我尝试了以下操作,但它不起作用

Profile.where("object_changes->'customer_id' @> '5'")

Profile.where("object_changes->'customer_id' @> ?::jsonb", [5].to_json)

Profile.where("? = ANY (object_changes->>'customer_id')", 5)

有谁知道我如何能够在 Ruby on Rails 中进行此查询。

我的 Rails 版本是 Rails 4.2,Ruby 版本是 2.4.10,我使用 postgres 作为我的数据库

【问题讨论】:

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


    【解决方案1】:

    我认为您需要的是jsonb_to_recordset 和横向连接的组合。

    对于以下架构和数据

    CREATE TABLE profiles (
      id integer,
      item_type text,
      object_changes jsonb
    );
    
    INSERT INTO profiles(id, item_type, object_changes) VALUES
      (1, 'Item', '[{"customer_id": [1, 5], "other_id": 1}, {"customer_id": [4, 5], "other_id": 2}]'::jsonb),
      (2, 'Item', '[{"customer_id": [3, 6], "other_id": 3}, {"customer_id": [3, 5], "other_id": 2}]'::jsonb),
      (3, 'Item', '[{"customer_id": [4, 7], "other_id": 3}, {"customer_id": [8, 9], "other_id": 2}]'::jsonb);
    

    这样的事情会起作用:

    SELECT distinct profiles.*
    FROM 
      profiles, 
      jsonb_to_recordset(profiles.object_changes) AS changes(customer_id integer[], other_id integer)
    WHERE 5 = ANY(changes.customer_id);
    
    
     id | item_type |                                  object_changes
    ----+-----------+----------------------------------------------------------------------------------
      2 | Item      | [{"other_id": 3, "customer_id": [3, 6]}, {"other_id": 2, "customer_id": [3, 5]}]
      1 | Item      | [{"other_id": 1, "customer_id": [1, 5]}, {"other_id": 2, "customer_id": [4, 5]}]
    (2 rows)
    

    因此,AR 查询界面的最终解决方案类似于(我硬编码要查找的值,但我相信您明白了,参数化不是问题):

    Profile.find_by_sql(<<~SQL)
      SELECT distinct profiles.*
      FROM 
        profiles, 
        jsonb_to_recordset(profiles.object_changes) AS changes(customer_id integer[], other_id integer)
      WHERE 5 = ANY(changes.customer_id)
    SQL
    

    【讨论】:

    • 我最终得到一个错误 PG::InvalidTextRepresentation: ERROR: malformed array literal: for the customer_id integer[]
    猜你喜欢
    • 2018-02-22
    • 1970-01-01
    • 2018-03-29
    • 2015-11-28
    • 2016-06-14
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多