2

Problem

Find all records in sample data where foo->bar include at least one item from given array e.g. [1,2]

Sample data

Record 1 => 'foo': {
  'bar': [1,2]
}

Record 2 => 'foo': {
  'bar': [3,4]
}

Record 3 => 'foo': {
  'bar': [5,7]
}

Record 4 => 'foo': {
  'bar': [1]
}

Record 5 => 'foo': {
  'bar': [2,3]
}

Expected result

Record 1 => 'foo': {
  'bar': [1,2]
}


Record 4 => 'foo': {
  'bar': [1]
}

Record 5 => 'foo': {
  'bar': [2,3]
}

I tried using operators @> and ?|, the first checks against JSOB and returns only if all items are included. Second has issues with types JSOB => Integer[]

SQL

SELECT  "some_table".* FROM "some_table" WHERE (foo->'bar' @> '[1,2]'::jsonb);

Rails Scope

scope :for_bar, -> (bars) { where("foo->'bar' @> ?::jsonb", bars.to_json) }

Any suggestions to solve this.

3 Answers 3

6

I think what you need is:

  • extract bar from foo,
  • map any element from bars to JSON,
  • cast the bound values to array,
  • cast the array of bound values to jsonb[],
  • check if any of the left JSON values contain the right JSON path/value entries at the top level (@>):
SomeTable.where("foo->'bar' @> ANY(ARRAY[?]::JSONB[])", [1, 2].map(&:to_s))
Sign up to request clarification or add additional context in comments.

1 Comment

Makes total sense, Thanks a ton.
0

One possible solution is to use jsonb_array_elements() to unroll the JSON arrays into sets. Then, in an EXISTS subquery, inner join these sets on common elements.

SELECT *
       FROM some_table
       WHERE EXISTS (SELECT *
                            FROM jsonb_array_elements(some_table.foo->'bar') t (v)
                                 INNER JOIN jsonb_array_elements('[1,2]'::jsonb) s (v)
                                            ON t.v = s.v);

db<>fiddle

Comments

-2
MyTable.where("my_attr->'jsonb_field' @> ANY(ARRAY[?]::JSONB[])", ['Mary'.to_json, 'Jane'.to_json])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.