12

I am using Postgres' JSON data type to store some information.

For example I have model User with a field locations that holds a json document(array of objects containing pairs of keys and values) in the following format:

[{"name": "Location 1", kind: "house"},
 {"name": "Location 2", kind: "house"},
 {"name": "Location 3", kind: "office"},
 ...
 {"name": "Location X", kind: "house"}
]

I want to query with .where on the JSON data type.

I want to query for users that have at least one location with kind = office.

Thanks!

1

5 Answers 5

18

I want to query for users that have locations with kind office

# if locations is jsonb type
User.where('locations @> ?', { kind: 'office' }.to_json)
# if locations is json type
User.where("locations->>'kind' = 'office'")
# if locations is array of hashes
User.where('locations @> ?', [{ kind: 'office' }].to_json)
Sign up to request clarification or add additional context in comments.

9 Comments

@> is jsonb operators. Unfortunately, I have json.
I've tried, but it's not working. It alway returns an empty result.
@mamantoha how come? It is the way you query json pg column. What's the issue with that?
I think the problem is array of hashes.
Anyway, thank you for your help. I migrate my data from json to jsonb. And this works for me User.where('locations @> ?', [{ kind: 'office' }].to_json)
|
6

I have used a mix of above answers. This is my working code:

User.where("locations::jsonb @> ?", [{kind: 'office'}].to_json)

As a note, locations is a JSON column of User table (not JSONB datatype)

Comments

4

Filters based on the values of objects inside array JSONB

If you want to make filters based on the values of the objects (jsonb) inside the arrays in Rails with postgres you can use something like example below.

Assuming you have a Product model:

Product.select("*").from(
  Product.select("*, jsonb_array_elements(registers) as register")
).where("(register ->> 'price')::numeric >= 1.50")

In above example we select all products with price greater than or equal 1.50.

For this we use:

I applied ident in sub-query just for best readability.

After you can put this in a scope or use other best practice.

Comments

3

Source: https://www.postgresql.org/docs/current/static/functions-json.html

User.where("name::jsonb -> 'location' ->> 'kind' = ?", 'office')

Comments

2

Just to give my two cents:

I have a model with a JSON with a key and an array inside, so it looks like this:

ModelObj: attribute: { key: [val0, val1, val2, val3] }

I needed to find all objects with, for example, attributes where the key has val3 in the array. I changed my attribute type to jsonb and this was how I find it:

Model.where('attribute @> ?', {key: ['val3']}.to_json)

Maybe it's useful to someone out there.

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.