Modify array inside of jsonb object - arrays

I've got a table column (columnName) that holds an object. One of those object's properties (objectKey) is an array of strings. I want to prepend to that array a single value (newValue). I cannot for the life of me figure out how to do this from the DB.
The closest I can get it do the following:
ARRAY['newValue'] || (columnName::jsonb->>'objectKey')
But that escapes all the characters in the original array and is technically making the original array an element in the a new array.
Is there a simple way to do this in the database?
A sample of my column looks like this:
{"objectKey":["one","two","three"],"objectKey2":["one","two","three"]}
After running a script I'd like it to be:
{"objectKey":["newValue","one","two","three"],"objectKey2":["one","two","three"]}

You can use jsonb_set() to add a value to an array. The syntax is a bit clumsy though. You need to "fake" it with a non-existing index.
jsonb_set(the_column, '{objectKey,-9999}'::text[], '"newValue"'::jsonb, true)
The 9999 is simply a non-existing array index and by using a negative value, the new element is added at the beginning of the array as documented in the manual
Alternatively you can use || to concatenate two objects:
To append a value you can use the || operator as suggested by Abelisto:
jsonb_set(the_column, '{objectKey}', (the_column -> 'objectKey') || '["newValue"]')
To add the element at the start:
jsonb_set(the_column, '{objectKey}', '["newValue"]' || (the_column -> 'objectKey'))
Online example

Related

How to save bucket names to a string and add new ones after that to an array

i have planner buckets (Tasks, in progress, Backlog) and I want to create a new Bucket depending on elements in a SharePoint list.
But I can't save the bucket names to an array and then add the missing value e.g. like "on hold" and the go trough the array again. It always set my array to blank again.
Maybe you can help me. Here is my PowerAutomate Flow so far:
You could use a couple of Select actions to create two arrays which you can use for the comparison. With a Filter Array you can find the ones which are missing. The output of that Filter Array can be used to loop through and create the missing buckets.
Below is an example of that approach.
1. In both Select actions the Map field is switched to text mode to only get Arrays with values (without keys)
2. In the Filter Array this is used in the From
body('Select_-_SharePoint_Items')
3. And this is the expression used in the advanced mode
#not(contains(body('Select_-_Existing_Buckets'), item()))

How to index a dataframe with a user-defined string?

Assumptions: I have a Julia DataFrame with a column titled article_id.
Normally, I can declare a DataFrame using some syntax like df = DataFrame(CSV.File(dataFileName; delim = ",")). If I wanted to get the column pertaining to a known attribute, I could do something like df.article_id. I could also index that specific column by doing df."article_id".
However, if I created a string and assigned it to the value of article_id, such as str = "article_id", I cannot index the dataframe via df.str: I get an error by doing so. This makes sense, as str is not an attribute of the DataFrame, yet the value of str is an attribute of the DataFrame. How can I index the DataFrame to get the column corresponding to the value of str? I'm looking for some syntax similar to df.valueof(str).
Are there any solutions to this?
From the DataFrames.jl manual's "Getting started" page:
Columns can be directly (i.e. without copying) accessed via df.col, df."col", df[!, :col] or df[!, "col"]. The two latter syntaxes are more flexible as they allow passing a variable holding the name of the column, and not only a literal name.
So you can write df[!, str], and that will be equivalent to df.article_id if str == "article_id".
The Indexing section of the manual goes into even more detail, for when you need more advanced types of indexing or want a deeper understanding of the options.
For an additional reference. When you write:
df.colname
it is equivalent to writing getproperty(df, :colname). Therefore if you have column name stored in the str variable you can write getproperty(df, str).
However, as Sundar R noted it is usually more convenient to use indexing instead of property access. Two most common patterns are df[!, str] which is equivalent to getproperty(df, str) and gets you a column without copying it and df[:, str] which gets you a copy of a column.

Select the data from input

My app uses a select with different values, which work also as a search. Now if i click on save after i inserted 2 names i get an an array with 2 objects. After that if i will insert just 1 name and click save, the previous array is changed with a new one which is composed only from 1 element, in fact i deleted the first array, but i don't want to lose the previous array. I want to keep the previous array, and if i will add a value that not exists in it, i want to add the new value, and i fact i will have an array with 3 objects. How to solve this issue?
link to my app: https://codesandbox.io/s/affectionate-ritchie-oxhuk
Basically what you need to do, is to save after every Save buton click(i.e. to concat arrays) and save only the unique items.
if you are familer with ES6, you can use Set object of javascript. Its an handfull tool to choose unique items from an array.
Array.from(new Set(savedItems.concat(selectedItems)).values())
you can first concat the two array, then set them to a Set to remove the duplicates and then convert them back to the original Array.
https://codesandbox.io/s/objective-pascal-5fo3n

How to remove last character of last row in tmap using Talend?

I am extracting two columns using textractjson and passing it to a tmap component where I am concatenating both of the columns as single one.
Also, I want a comma at the end of each row except the last row.
I am not sure how to do this.
Example:
There are two columns in tmap as input:
FirstName
LastName
In output, I have concatenated them to:
FirstName+LastName+","
The problem is I dont want the comma in the last row.
This depends on your job layout and input structure.
You seem to use tExtractJSON, which could mean you get the data from a REST call or out of a database.
Since there is no fixed row amount because of the JSON data structure, you wouldn't be able to use ((Integer)globalMap.get("tFileInputDelimited_1_NB_LINE")). Again, since we don't know your job layout, this depends on it.
If this is not the case, I would count the rows in a tJavaRow component first and then add a second tJavaRow where I'd concat the strings (wouldn't do that in the tMap), but omit the last comma. I'd be able to find the last row with the count I did first. This depends on your Java skills.
You may also concatenate all the rows in a global variable using a tJavaRow, with a comma at the end for each row.
Then, start a new subjob (onSubjobOk) then using a tJava, remove the last character (so the last comma).
Pretty simple, don't have to know how many rows from the input flow but supposing you want the result as a single string (here contained in a global variable).
I might be wrong also. Basically concatenate FirstName and LastName , Create record number column using Numeric.Sequence() function and use one more context variable and store the same sequence number here(it might store last value) also in tJavaRow component.
output_row.name = input_row.FirstName+""+input_row.LastName+","+;
output_row.record_number = Numeric.sequence("recNo", 1, 1);
context.lastNumber = Numeric.sequence("recNo", 1, 1);
create a method in custom java routine.
public static string main _nameChange(String name,Integer record_number){
if(context.lastNumber == record_number){
name = name.substring(0,name.length()-1);
return name;
}
else{
return name;
}
}
Now call _nameChange method within tmap component. Now you can trim the last row's last character.
Ror reference check this

How to update keys in a JSON array Postgresql

I am using PostgreSQL 9.4.1 and have run into an issue with a column that I need to update. The column is of type JSON with elements in the following format:
["a","b","c",...]
["a","c","d",...]
["c","d","e",...]
etc.
so that each element is a string. It is my understanding that each of these elements are considered keys to the JSON array (please correct me if I am a bit confused here, I haven't ever worked with JSON datatype columns before, so I'm still trying to get a grip on them anyways). There is not an actual pattern to these arrays, and their contents are dependent on user input from somewhere else. My goal is to update any of the arrays that contain a particular element (say "b" for the purpose of explaining my question more thoroughly) and replace the content "b" with say "b1". Meaning that:
["a","b","c",...]
would be updated to
["a","b1","c",...]
I have found a few ways listed on this site (I don't currently have the links, but I can find them again if necessary) to update VALUES for a particular KEY, but I haven't found a way mentioned to change the KEY itself. I have already found a way to target the specific rows of interest by doing something similar to:
SELECT *
FROM TableA
WHERE column::json ?| ["b", other string elements of interest]
Any suggestions would be greatly appreciated. Thanks for your help!
So I went ahead and gave that a check (because it looks like it should work, and it's more or less what I ended up doing), but I figured out what I was trying to do! What I got was this:
UPDATE TableA
SET column = REPLACE(column::TEXT,'b','b1')::JSON
WHERE column::JSON ?| ['b']
And now that I think about it, I probably don't even need the last where condition because the replace won't affect anything that doesn't have 'b' in it. But that worked for me, and it looks like yours probably should too! Thanks for the help!
I wanted to rename a specific key for json array column.
I tried and it worked on PostgreSQL 9.4:
UPDATE Your_Table_Name
SET Your_Column_Name = replace(Your_Column_Name::TEXT,'Key_Old_Name','Key_New_Name')::json
WHERE attributes::jsonb ? 'Key_Old_Name'
Basically, solution is to go over the list of json_array_elements, and based on json value using CASE condition replace certain value with other one. After all, need to re-build new json array using array_agg() and to_json() description of aggregate functions in psql is here.
Possible query can be the following:
-- Sample DDL and JSON data
CREATE TABLE jsontest (data JSON);
INSERT INTO jsontest VALUES ('["a","b","c"]'::JSON);
-- QUERY
WITH result AS (
SELECT to_json( -- creating updated json structure
array_agg( -- create array with new element "b1"
CASE WHEN element::TEXT = '"b"' -- here we process array elements to find "b"
THEN to_json('b1'::TEXT)
ELSE element
END)) as new_json
FROM jsontest,json_array_elements(jsontest.data) as element
)
UPDATE jsontest SET data = result.new_json FROM result;

Resources