How can I compare json field with a string value in postgresql? - postgresql

I have a field payload saved in a postgresql table which is json type. This type has a nested field subcategory which is string. Below is the output of this value:
=> select payload->'subcategory' from "Merchant";
?column?
-------------------------------
"Food"
null
"AUTOMOTIVE"
null
"MEDICAL"
null
null
"CLUB"
"Petrol Stations"
However, I can't put this field in the where clause. Below query returns 0 rows. But from above output it shows there are rows whose value is CLUB. What is the right way to use json field in where clause?
=> select count(*) from "Merchant" where ("payload"->'subcategory')::text = 'CLUB';
count
-------
0

Figured out what's wrong, I need to use ->> in the where like "payload"->'subcategory'.
that because ->> converts it to text while -> makes it as JSONB

An alternative solution is to use the JSON contains operator #>:
select count(*)
from "Merchant"
where payload #> '{"subcategory": "CLUB")';

Related

How can I get the length of a property in a jsonb in postgres?

product
---------------------------
{"id":1, "code": "1231313"}
this is the query i made, but it doesn't work
SELECT * FROM public.order WHERE "product" ->> LENGTH('code') = '7';
I would like to know how I can get the length of the value of this property from a jsonb, please help me, thanks.
Below is the way to use the ->> operator to extract field from a column of type JSON(B) and then apply length() to get the text length.
select * from public.order where length(product->>'code') >= 7
See the various operators/functions to get data from JSON(B) column type, Postgresql documentation

Updating json columns in psql

I have a table containing a json column. The json values will look something like this:
{'john': 1, 'alex' : 4, 'harry' :2}
If I wanted to add 1 to john, how would I go about doing this?
demo:db<>fiddle
UPDATE mytable -- 6
SET mydata = jsonb_set( -- 4
mydata::jsonb, -- 1
'{john}', -- 2
((mydata ->> 'john')::int + 1)::text::jsonb -- 3
)::json; -- 5
Fetch your data. If it is of type json, cast it into type jsonb
Path to your requested element as text array
Fetch the original value. ->> operator returns type text, so to do an integer operation, you need to cast it into type int. Then add the 1. This result must be reconverted into type jsonb. Unfortunately type int cannot be cast into type jsonb directly, so take the intermediate step via type text
Use jsonb_set() to update the JSON object specified in (1)
If your column is of type json instead of jsonb, cast the result back into type json
Perform the update

Build jsonb array from jsonb field

I have column options with type jsonb , in format {"names": ["name1", "name2"]} which was created with
UPDATE table1 t1 SET options = (SELECT jsonb_build_object('names', names) FROM table2 t2 WHERE t2.id= t1.id)
and where names have type jsonb array.
SELECT jsonb_typeof(names) FROM table2 give array
Now I want to extract value of names as jsonb array. But query
SELECT jsonb_build_array(options->>'names') FROM table
gave me ["[\"name1\", \"name2\"]"], while I expect ["name1", "name2"]
How can I get value in right format?
The ->> operator will return the value of the field (in your case, a JSON array) as a properly escaped text. What you are looking for is the -> operator instead.
However, note that using the jsonb_build_array on that will return an array containing your original array, which is probably not what you want either; simply using options->'names' should get you what you want.
Actually, you don't need to use jsonb_build_array() function.
Use select options -> 'names' from table; This will fix your issue.
jsonb_build_array() is for generating the array from jsonb object. You are following wrong way. That's why you are getting string like this ["[\"name1\", \"name2\"]"].
Try to execute this sample SQL script:
select j->'names'
from (
select '{"names": ["name1", "name2"]}'::JSONB as j
) as a;

kdb+/q table - convert string to number

assume you have a table
tbl:([] id:("123"; ""; "invalid"))
And want to parse this string into a number.
Invalid values - in the example above, both the empty string "" as well as the value "invalid", should be parsed to null (0Nj).
How can you best do it? My initial approach was
select id:.[value;;0Nj] each enlist each id from tbl
But while that will parse the both the "123" as well as "invalid" entries correctly, it will return the unary operator :: instead of null when trying to parse the row with the empty string.
Of course I could do something like
select id:.[value;;0Nj] each enlist each id from update id:string (count id)#`invalid from tbl where id like ""
but this seems kind of.. ugly/inefficient. Is there any better way to do this?
Thanks
Try "J"$ to cast the column
q)select "J"$id from tbl
id
---
123
https://code.kx.com/v2/ref/tok/
how about just cast it to long?
q)update id:"J"$id from `tbl
`tbl
q)select from tbl where not null id
id
---
123

Parse jsonb field - PostgreSQL

I have a field that is of type jsonb in a PostgreSQL database.
Example:
{"timestamp":"2016-12-14T04:15:04.836Z","receiptResult":{"status":"successful","timestamp":"2016-12-14T04:15:04.739Z","notes":"Customer Accepted"}}
How can I only return the "notes" in a select statement, I've tried:
SELECT data::json->>'notes' as notes
But nothing is returned, if I use:
SELECT data::json->'receiptResult' as notes;
It returns:
{"status":"successful","timestamp":"2016-114T04:15:04.739Z","notes":"Customer Accepted"}
But I only need the text after "notes".
Inside key receiptResult has another JSON object, you cannot access it in top-level. Try this:
WITH sample AS (
SELECT '{"timestamp":"2016-12-14T04:15:04.836Z","receiptResult":{"status":"successful","timestamp":"2016-12-14T04:15:04.739Z","notes":"Customer Accepted"}}'::jsonb AS my_column
)
SELECT my_column->'receiptResult'->>'notes' FROM sample;
As you can see, -> operator returns value as a JSONB and ->> operator returns as a text.
More info here.