简体   繁体   中英

Rails: Search array json fields in postgresql db

Seriously struggling to come up with a rational scope.

I want to get a list of Model which have a specific "type" field inside of a json array column using postgresql.

Could someone point me in the right direction, also, I am fine with this being a class level method instead of a scope, I just need a list of all the Model.objects .

The main model is Submission, which has_one :fmp_session -- FmpSession has a field : project_data, which is a postgresql :json type field, containing a json array.

So what I want is an active record array of all submissions if the fmp_session.project_data 'type' json key equals 'CREW'.

I'd rather stick with activerecord or sql (or mix and match) and leave AREL alone.

I was thinking something like this:

Submission.joins(:fmp_session).where(
    'EXISTS(
        SELECT 1 from json_array_elements(
            "project_data"
            ) project_data WHERE (
            project_data#>> "{type}"
        ) = "CREW"
    )'
)

In theory, this would search the project_data array, and searches it with #>> so it doesn't matter how many elements are in the array -- but I have tried close to 40 machinations of the query and am stuck. Help me find the right query to join one table to another and search an json array field for a specific string.

UPDATE

To show the database portion, here is the table description (from psql) and the the schema.db segments for this table. Additionally you should know

 Column        | Type      |Modifiers
---------------+-----------+-----------------------------------------------------------
 id            | integer   | not null default nextval('fmp_sessions_id_seq'::regclass)
 project_data  | json      | default '[]'::json

And the schema

  create_table "fmp_sessions", force: :cascade do |t|
    t.json     "project_data",        default: []
    t.json     "project_member_data", default: []
    t.datetime "created_at",                       null: false
    t.datetime "updated_at",                       null: false
  end

Probably your problem in quotation:

Submission.joins(:fmp_session).where(
    "EXISTS(
        SELECT 1 from json_array_elements(
            project_data
            ) project_data WHERE (
            project_data#>> '{type}'
        ) = 'CREW'
    )"
)

UPD: Answer to comment

Query is useful:

SELECT project_data#>> '{name}'
 from json_array_elements(
'[
            {
                "id": "1",
                "name": "First",
                "type": "CREW"
            },
            {
                "id": "2",
                "name": "Second",
                "type": "NOCREW"
            },
            {
                "id": "3",
                "name": "Third",
                "type": "CREW"
            }
]'
            ) project_data
WHERE project_data#>>'{type}' = 'CREW'
;


 ?column? 
----------
 First
 Third
(2 rows)


SELECT EXISTS (SELECT 1
 from json_array_elements(
'[
            {
                "id": "1",
                "name": "First",
                "type": "CREW"
            },
            {
                "id": "2",
                "name": "Second",
                "type": "NOCREW"
            },
            {
                "id": "3",
                "name": "Third",
                "type": "CREW"
            }
]'
            ) project_data
WHERE project_data#>>'{type}' = 'CREW'
)


 exists 
--------
 t
(1 row)

UPDATE 2: PG12 features.

PG12 added a few excelent fetures that allow to work with arrays in json:

SELECT project_data @? '$[*] ? (@.type == "CREW")' AS res
  FROM (SELECT '[
        {"id": "1","name": "First","type": "CREW"},
        {"id": "2","name": "Second","type": "NOCREW"},
        {"id": "3","name": "Third","type": "CREW"}
       ]'::jsonb AS project_data) AS j;
                                                             
res
----------
 t
(1 row)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM