how to modify an array jsonb in postgresql? - arrays

In postgresql,I have a table which defined like this:
create table carts(
id serial,
cart json
)
has data like this:
id cart
3 [{"productid":5,"cnt":6},{"productid":8,"cnt":1}]
5 [{"productid":2},{"productid":7,"cnt":1},{"productid":34,"cnt":3}]
if i want to modify the data "cnt", with id=n and productid=m,
how can I do this?
for example, when id=3,and productid=8, i want to change the cnt to cnt+3,
how to realize it?

Try This, here we will use jsonb_set method
jsonb_set(target jsonb, path text[], new_value jsonb) which will return jsonb object
update carts
set cart = (
(select json_agg(val)from
(SELECT
CASE
WHEN value->>'productid'='8' THEN jsonb_set(value::jsonb, '{cnt}', (((value->>'cnt')::int)+3)::text::jsonb)::json --again convert to json object
ELSE value END val
FROM carts,json_array_elements(cart) where id=3))
where id=3;
Hope it works for you
EDIT: you can generalized this by creating a function with id and
productid as input parameter.

Related

Postgresql: Append object to a list

I have data that has a key as string and value is a list of json, looks like
ID|data
A1|{key1:[{k1:v1,k2:v2},{{k3:v3,k4:v4}]}
I want to append json, say, {k9:v9,k7:v6} to this list for the key1, something like-
ID|data
A1|{key1:[{k1:v1,k2:v2},{{k3:v3,k4:v4},{k9:v9,k7:v6}]}
I have tried jsonb_set and other functions but they were of no use, example-
UPDATE tbl_name
SET data = jsonb_set(data,'{key1,1}','{k9:v9,k7:v6}'::jsonb) where ID = 'A1'
You need to use jsonb_insert() function in order to append that part, after fixing the format of JSONB value ( otherwise you'd get "ERROR: invalid input syntax for type json" ) :
UPDATE tbl_name
SET data = jsonb_insert(data,'{key1,1}','{"k9":"v9","k7":"v6"}'::jsonb)
WHERE ID = 'A1'
Demo

SQL Server: How to remove a key from a Json object

I have a query like (simplified):
SELECT
JSON_QUERY(r.SerializedData, '$.Values') AS [Values]
FROM
<TABLE> r
WHERE ...
The result is like this:
{ "2019":120, "20191":120, "201902":121, "201903":134, "201904":513 }
How can I remove the entries with a key length less then 6.
Result:
{ "201902":121, "201903":134, "201904":513 }
One possible solution is to parse the JSON and generate it again using string manipulations for keys with desired length:
Table:
CREATE TABLE Data (SerializedData nvarchar(max))
INSERT INTO Data (SerializedData)
VALUES (N'{"Values": { "2019":120, "20191":120, "201902":121, "201903":134, "201904":513 }}')
Statement (for SQL Server 2017+):
UPDATE Data
SET SerializedData = JSON_MODIFY(
SerializedData,
'$.Values',
JSON_QUERY(
(
SELECT CONCAT('{', STRING_AGG(CONCAT('"', [key] ,'":', [value]), ','), '}')
FROM OPENJSON(SerializedData, '$.Values') j
WHERE LEN([key]) >= 6
)
)
)
SELECT JSON_QUERY(d.SerializedData, '$.Values') AS [Values]
FROM Data d
Result:
Values
{"201902":121,"201903":134,"201904":513}
Notes:
It's important to note, that JSON_MODIFY() in lax mode deletes the specified key if the new value is NULL and the path points to a JSON object. But, in this specific case (JSON object with variable key names), I prefer the above solution.

find number in json array value with regex

i want match string in json string that like:
"ids":[44,53,1,3,12,45]
i want run query in sqlite send only one digit as id and match one of the above id in sql statement
i write this regex "ids":[\[] for matching start of key
but i don't have any idea to match middle id and escape starting id
example:
i have calc_method table like this:
CREATE TABLE "calc_method" (
"calc_method_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"calc_method_name" TEXT NOT NULL,
"calc_method_value" TEXT NOT NULL
);
in calc_method_value column i store calcMethod class which convert to json using Gson
class calcMethod{
var memberCafeIds:ArrayList<Long>,
var memberBarIds:ArrayList<Long>
}
after i convert calcMethod to json i have output like below and this value store in calc_method_value column:
{"memberCafeIds":[1,2,14,5,44],"memberBarIds":[23,1,5,78]}
now i want select row that match to my regex pattern like if calc_method_value column have memberBarIds with id 1
SELECT * FROM calc_method WHERE calc_method_value REGEXP '"memberCafeIds":\[[:paramId]'
:paramId is method parameter
Regards, a programmer struggle with regex
In Sqlite, use JSON1 functions to work with JSON, not regular expressions. In particular, json_each() to turn the JSON array into a table you can query:
sqlite> CREATE TABLE ex(json);
sqlite> INSERT INTO ex VALUES ('{"ids":[44,53,1,3,12,45]}');
sqlite> SELECT * FROM ex WHERE 1 IN (SELECT value FROM json_each(ex.json, '$.ids'));
json
-------------------------
{"ids":[44,53,1,3,12,45]}
sqlite> SELECT * FROM ex WHERE 50 IN (SELECT value FROM json_each(ex.json, '$.ids'));
sqlite>

Select on jsonb array on specific key/value

I have a jsonb field containing this data :
[{"FieldName":"wire1","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]},
{"FieldName":"wire2","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]},
{"FieldName":"wire3","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]}]
What is the correct way to access the FieldName = FieldValue inside this array, as part of a select ? We tried SELECT meta::json->0 FROM myTable , and that returned null. (meta is the column's name containing the metaData)
What I hope to get is, in a select, to return all lines where FieldName = wire1, or where Source = exampleSource, or where both are true.
what you need is jsonb_array_elements function.
-> returns an object
SELECT jsonb_array_elements(**columnName**)->'FieldName' FROM ....
returns FieldName object
->> returns text
SELECT jsonb_array_elements(**columnName**)->>'FieldName' FROM ....
returns "wire1" text

MSSQL JSON_VALUE to match ANY Object in Array

I have a table with a JSON text field:
create table breaches(breach_id int, detail text);
insert into breaches values
( 1,'[{"breachedState": null},
{"breachedState": "PROCESS_APPLICATION",}]')
I'm trying to use MSSQL's in build JSON parsing functions to test whether ANY object in a JSON array has a matching member value.
If the detail field was a single JSON object, I could use:
select * from breaches
where JSON_VALUE(detail,'$.breachedState') = 'PROCESS_APPLICATION'
but it's an Array, and I want to know if ANY Object has breachedState = 'PROCESS_APPLICATION'
Is this possible using MSSQL's JSON functions?
You can use function OPENJSON to check each object, try this query:
select * from breaches
where exists
(
select *
from
OPENJSON (detail) d
where JSON_VALUE(value,'$.breachedState') = 'PROCESS_APPLICATION'
)
Btw, there is an extra "," in your insert query, it should be:
insert into breaches values
( 1,'[{"breachedState": null},
{"breachedState": "PROCESS_APPLICATION"}]')

Resources