Query PostgresSQL(9.6.5) JSONb Column with Rails 5.1.6 For multiple key value pairs - postgresql-9.6

I have a column in my database called events.
t.jsonb "events"
There I store an array have hashes.
[{ type: 'bounce', bounce_class: '25'}...]
I can find the records that have a hash with the key: value pairs of type: 'bounce' and bounce_class: '25' by using this where statement.
where("events #> ?", [{type: "bounce", bounce_class: '25'}].to_json)
What I can't figure out is how to look for multiple values in the bounce class key: value pair without chaining a bunch of or statements like this.
where("events #> ?", [{type: "bounce", bounce_class: '25'}].to_json).or(where("events #> ?", [{type: "bounce", bounce_class: '26'}].to_json))
I would like to find all the records that have a type: 'bounce' and have a bounce_class of '25' or '26, or '50'.
Is there a better way than chaining or statements?
Thanks

Related

Ruby on Rails and POSTgres: Search IN an array within JSON field [duplicate]

I have a table with a jsonb column that has a nested json array. I would like to find all records where the nested array contains at least one of a value.
For instance, my model Person has a jsonb column named preferences. Inside the jsonb preferences, there are a few keys, one of which the value is an array:
Person.first.preferences = {"diet" => {"foods" => ["apples", "oranges", "bananas"]}}
I would like to create a query that returns all Persons whose preferences -> diet -> foods include 'apples' OR 'mangos' (for example).
Currently, I can get results with 1 input (ie. 'apples') like this:
Person.where('preferences #> ?', {'diet' => {'foods' => ['apples']}}.to_json)
And multiple inputs, if they all exist in the array. So if I pass in 'apples' and 'oranges', the result is returned because the record includes BOTH apples and oranges.
Person.where('preferences #> ?', {'diet' => {'foods' => ['apples', 'oranges']}}.to_json)
Is there a way to pass in multiple variables (ie. ['apples', 'mangos']) and check if the nested jsonb array contains either apples OR mangos but not necessarily both?
The following query has no results, because my Person's food preferences don't include mangos, even though they include apples.
Person.where('preferences #> ?', {'diet' => {'foods' => ['apples', 'mangos']}}.to_json)
Using Rails 5.2 and Postgresql 10
Thanks!
The first thing to do is to get to the array using -> or #> and then you can use the ?| operator to check if the array overlaps what you're looking for. Something like this SQL:
preferences->'diet'->'foods' ?| array['apples', 'mangos']
or with ActiveRecord:
Person.where("preferences->'diet'->'foods' ?| array[:foods]", foods: ['apples', 'mangos'])

Active Record query array of Json

I have a json column (is an array of objects) in my db containing the many categories related to a product like this:
[
{
"id": 1,
"name": "Category X"
},
{
"id": 2,
"name": "Category Y"
},
...
]
I need to translate into active record query the following PostgreSQL query:
SELECT * FROM products p, json_array_elements(p.category) as data
WHERE data ->>'name' = 'Sport';
Some of queries that I tried:
sports = Product.where("category ->>'name' = ?", "Sport")
Which returns an empty array (It is wrong since I have records with Sport category in my db)
sports = Product.where("category #> ?", [{name: "Sport"}])
Which raises: TypeError: can't quote Hash
sports = Product.where("category #> ?","{name: 'Sport'}")
Which raises: ERROR: operator does not exist: json #> unknown
and the Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
So I tried:
sports = Product.where("category #> ?", "[{'name': 'Sport'}]")
and
sports = Product.where("category #> ?", "[{'name': 'Sport'}]".to_json)
and some other queries all without success.
These links:
PostgreSQL functions-json
active record querying
didn't help much.
The reason why you're getting a PG::UndefinedFunction: exception ("operator does not exist: json #> unknown") is because the #> operator is meant to be used in jsonb data type columns, and your products.category column isn't.
For that you can; or to update the data type of the category column, or to explicitly cast the column at the moment of performing the query:
Product.where('category::jsonb #> ?', [{ name: 'Sport' }].to_json)
This:
Product.where("category #> ?", "[{'name': 'Sport'}]")
isn't going to work, since it's not valid syntax.

ActiveRecord & Postgresql: Query jsonb attribute

I have a model Characteristic, with a equivalent attribute which is a jsonb value.
ex:
characteristic1:
id:1
equivalent: {list: ['first', 'second', 'third']}
characteristic2:
id:2
equivalent: {list: ['fourth', 'fifth', 'sixth']}
How can I find the record with second in the list using active record query interface?
Found a way:
Characteristic.where("equivalent -> 'list' ? 'second' ")

Rails postgres hstore: query for a specific key with any of the given values

My question is specific to rails+postgres hstore datatype.
The WHERE IN [1,2, 3] or the rails equivalent Model.where(data: [1,2,3]) works fine for regular columns, but not for hstore.
I have a hstore column(say info) and I want to query for rows which have a particular key and any one of the given values.
For example: To find all books that have a key as 'author' and value as 'ABC' in hstore column, the following query works fine:
Book.where("info #> hstore(:key, :value)", key: "author", value: "ABC")
But I need a query that returns records which have a key as 'author' and any one of values in ['ABC', 'XYZ', 'PQRS', 'DFG'].
Any suggestions?
Maybe try:
Book.where("(info -> :key) IN (:values)", key: 'author', values: ['ABC', 'XYZ'])
However, #> has index support, while this won't use any indexes.

Model has a field which is an array of strings, how can I find all records that contain a certain string in the array?

My model has a field called user_ids, which is an array of strings. How can I find all of the records which include a certain string, string_1, in user_ids?
I'm using Rails 3.0.1 & Ruby 1.9.2p0.
You can use something like this scope:
scope :some_scope_name, lambda {|user_id| where(["user_ids RLIKE ?", user_id])}
I used this type of scope in project, where I have to find all records with list_ids column match some criteria.
.. or you can use find_by_sql method with same SQL: ["user_ids RLIKE ?", criteria]

Resources