Ruby Rails, JSON - match results if key exists - ruby-on-rails

The set up is ruby on rails, in a postgres database. The table is called line_sources and a JSON column is called names. I want to return all rows where the names column contains a key called away_names. I'm trying this but they fail:
LineSource.where("names -> 'away_names'")
and
LineSource.where("names ->> 'away_names' = '%'")

Try this :
where("(names->'away_names') is not null")

You can use #> to get the JSON object at that path.
where("(names #>'{away_names}') is not null")
Basic key operators to query the JSON objects :
#> : Get the JSON object at that path
->> : Get the JSON object at that path as text
{obj, n} : Get the nth item in that object

Related

How to get data from a property with a JSON document embedded using Cypher

I have the following case:
I have some information stored in Neo4j. One property store a JSON document, and I would like to get the information inside this JSON document.
I have retrieved the data, even the JSON field using MATCH:
MATCH (n:Node) RETURN n.id, n.nodeInfo as JSONInfo
JSONInfo (which is a property of Node), has the JSON Information:
{
"TIMESTAMP":"2018-03-11T04:58:24Z",
"field1":"358716053191804",
"field2":"732111149743974",
"version_field", "3.9.1"
"field3":"0",
"field4":"0"
}
But, I just want to get field1, that has inside JSON property.
What is the best way to retrieve this field in the MATCH command?
Thanks in advance
First of all your example isn't valid JSON. Your version_field key and value should be separated by a colon, not a comma, and you need a comma after "3.9.1".
{ "TIMESTAMP":"2018-03-11T04:58:24Z", "field1":"358716053191804", "field2":"732111149743974", "version_field":"3.9.1", "field3":"0", "field4":"0" }
Once that's fixed, and the field is valid JSON, you can use JSON conversion functions from APOC Procedures to do the conversion from a JSON object to a map, then just use dot notation to access map properties:
MATCH (n:Node)
RETURN apoc.convert.fromJsonMap(n.nodeInfo).field1 as field1
Keep in mind that map properties in JSON map strings cannot be indexed, so the data within your JSON string property should be used for storage and retrieval, not for lookup.

How to search using Activerecord in a json field stored as text in DB

I have a Json field stored in DB as text.
I want to look for records that contain Harvard as a value for those keys
json_data['infoOnProgram']['universityName']
How should I construct my where request to search on that Json field.
Student.where(json_data...
Thank you!
If there are a not very many records you can do this, which will be very expensive:
harvard_students = Student.map {|stud|
hash = JSON.parse(stud.json_data)
hash['infoOnProgram']['universityName'] == 'Harvard' ? stud : nil
}.compact
if you have lots and lots of records to iterate through you can limit your list with a regex query:
Simple
Student.where("json data like '%Harvard%'")
slightly better
Student.where("json data like '%infoOnProgram%universityName%Harvard%'")
The problem is without knowing how the data is structured it is hard to create a specific regex. You can use the where to limit and the iteration to confirm more precisely that these records are what you are looking for.
If you're sure you really do have valid JSON in your text column then you could cast it to jsonb (or json) and use the usual JSON operators and functions that PostgreSQL provides:
Student.where(
"json_data::jsonb -> 'infoOnProgram' ->> 'universityName' = ?",
'Harvard'
)
Student.where(
'json_data::jsonb -> :info ->> :name = :uni',
info: 'infoOnProgram',
name: 'universityName',
uni: 'Harvard'
)
Student.where(
'cast(json_data as jsonb) #>> array[:path] = :uni',
path: %w[infoOnProgram universityName],
uni: 'Harvard'
)
This is going to be an expensive query though as you won't be able to use any indexes. You really should start the process of changing the column's type to jsonb, that would validate the JSON, avoid having to type cast in queries, allow indexing, ...

Ruby Rails, JSON - match results if value exists

The set up is ruby on rails, in a postgres database. The table is called line_sources and a JSON column is called names. I want to return all rows where the names column contains a value called name1. I'm trying this but it fails:
LineSource.where("names ->> '%' = 'name1'")
Perhaps jsonb can be used for that?

rails AR query filtering records using postgres json data type

My postgres json data looks like this:
changes: {"data"=>[nil, {"margin"=>0.0, "target"=>0.77777}]}
The field name is changes and it's a postgres json data type.
How do I write an active record query to check for rows where data has a key named margin?
For example, the first record would be included while the second would not:
# record 1
changes: {"data"=>[nil, {"margin"=>0.0, "target"=>0.77777}]}
# record 2
changes: {"data"=>[nil, {"foo"=>0.0, "target"=>0.77777}]}
I've tried something like the following but it's not working:
ModelName.where("changes -> 'data' ?| array[:keys]", keys: ['margin'])
Okay, this is what I found
Query based on JSON document
The -> operator returns the original JSON type (which might be an object), whereas ->> returns text
Also, this post is probably what you look for.
Maybe try something like
ModelName.where("changes->>'margin' > -1")
The answer:
ModelName.where("changes -> 'data' -> 1 ? 'margin'")
The query logic is something like...in the changes field, move to object data, get second element (zero based index), see if it contains a key named margin.

ActiveRecord: search by array field element inside another array

I have an object with an array field, called emails
user.emails = ['a#b.c','d#e.f']
I want to find all the users from a list of emails:
emails_to_find = ['a#b.c','x#y.z']
I tried running
User.where(emails: emails_to_find)
but I get
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: array value must start with "{" or dimension information
How do I do that? What the error means?
If the column is of type Array and in the migration that created it you have something like t.string 'emails', array: true, try using:
User.where("emails #> ARRAY[?]::varchar[]", ['a#b.c','d#e.f'])
User.where("'a#b.c' = ANY (emails)")

Resources