TSQL JSON Add an array to an existing Json array in Java? - sql

We have a SQL query that updates a column, storing an array as a string.
internal_capabilites: ["1234"]
DECLARE #event nvarchar(4000)
SET #event = :capabilites
UPDATE destination_master
SET
internal_capabilites = JSON_MODIFY(JSON_QUERY(internal_capabilites, '$'),'append $',JSON_QUERY(#event)),
updated_by = :updatedBy
We need to add another dimension to the array in the internal_capabilites column.
List<String> s = new ArrayList<>();
s.add("2345");
("capabilites", JsonHelper.getInstance().serializeToString(s));
The result should be like this:
internal_capabilites: ["1234","2345"]
With the query, however, we are getting this result: ["1234",["2345"]]
We've tried this as well: TSQL JSON How to add an array to an existing Json Object?
How can we fix this?

Related

PostgreSQL update JSONB column from JSON string to Array of JSON objects

I am trying to update the value of a JSONB column from a JSON string like :
{"fruit":"apple", "color":"blue"}
to an array of JSON objects like :
[{"fruit":"apple"}, {"color":"blue"}]
I tried the following command :
UPDATE table_name SET data = json_build_array(data::JSONB);
It however gave me the following :
[{"fruit":"apple","color":"blue"}]
What can I use to get separate JSON objects in the array?
You can access each key-value pair in the JSON object using json_each, and then aggregate the results into an array:
update table_name set data = (select json_agg(json_build_object(v.key, v.value))
from json_each(data) v)
See fiddle.

POSTGRES JSON: Updating array value in column

I am using POSTGRES SQL JSON.
In json column the value is stored as array which I want to update using SQL query
{"roles": ["Admin"]}
The output in table column should be
{"roles": ["SYSTEM_ADMINISTRATOR"]}
I tried different queries but it is not working.
UPDATE public.bo_user
SET json = jsonb_set(json, '{roles}', to_jsonb('SYSTEM_ADMINISTRATOR')::jsonb, true);
UPDATE public.bo_user
SET json = jsonb_set(json, '{roles}', to_jsonb('["SYSTEM_ADMINISTRATOR"]')::jsonb, true);
ERROR: could not determine polymorphic type because input has type unknown
SQL state: 42804
Kindly help me with the query
but at the moment it is to update the value at 0 index
That can be done using an index based "path" for jsonb_set()
update bo_user
set "json" = jsonb_set("json", '{roles,0}'::text[], '"SYSTEM_ADMINISTRATOR"')
where "json" #>> '{roles,0}' = 'Admin'
The "path" '{roles,0}' references the first element in the array and that is replaced with the constant "SYSTEM_ADMINISTRATOR"' Note the double quotes inside the SQL string literal which are required for a valid JSON string
The WHERE clause ensures that you don't accidentally change the wrong value.
So this worked.
UPDATE public.bo_user
SET json = jsonb_set(json, '{roles}', ('["SYSTEM_ADMINISTRATOR"]')::jsonb, true)
where id = '??';

how to define a constant array and check if a value is in the array for Pig Latin

I want to define an array of user Ids in Pig and then filter data if the userId from the input is NOT in that array,
How do I do this in pig latin? Below is the example of what I intend to do
Thanks
inputData = load '$INPUT' USING PigStorage('|') AS (useriD:chararray,controllerAction:chararray,url:chararray,browserName:chararray,IsMobile:chararray,exceptionDetails:chararray,renderTime:int,serviceHostId:int,auditEventTime:chararray);
filteredInput = filter inputData by controllerAction is not null and auditEventTime is not null and serviceHostId is not null and renderTime is not null and useriD in ('2be2df06-f4ba-4d87-8938-09d867d3f2fe','ac1ac6bf-d151-49fc-8c7c-2b52d2efbb58','f00aec16-36e5-46ae-b7cb-a0f1eeefe609','258890f9-102a-4f8e-a001-ae24d2e25269','cf221779-a077-472c-b377-cca4a9230e1b');
Thanks Murali..I tried the approach of declaring a variable and then using Flatten and stringSplit to join..However I get the following error
Syntax error, unexpected symbol at or near 'flatteneduserids'
%declare REQUIRED_USER_IDS 'xxxxx,yyyyy,sssss' ;
inputData = load '$INPUT' USING PigStorage('|') AS (useriD:chararray,controllerAction:chararray,url:chararray,browserName:chararray,IsMobile:chararray,exceptionDetails:chararray,renderTime:int,serviceHostId:int,auditEventTime:chararray);
filteredInput = filter inputData by controllerAction is not null and auditEventTime is not null and serviceHostId is not null and renderTime is not null;
flatteneduserids = FLATTEN(STRSPLIT('$REQUIRED_USER_IDS',',')) AS (uid:chararray);
useridfilter = JOIN filteredInput BY useriD, flatteneduserids BY uid USING 'replicated';
so Now I tried another way of declaring flatteneduserids which results in the error Undefined alias: IN
flatteneduserids = FOREACH IN GENERATE FLATTEN(STRSPLIT('$REQUIREDUSERIDS',',')) AS (uid:chararray);
Had a similar use case. Tried the approach by declaring the constant value in %define and accessing the same inside IN clause, was not able to achieve the objective. (Refer : Declare a comma seperated string constant)
A thought worth contemplating ....
If the condition inside IN clause is a static/ reference/ meta kind of data, then would suggest to declare this in a static file. We can then read the data at run time and do an inner join with input data to retrieve the matching records.
input_data = LOAD '$INPUT' USING PigStorage('|') AS (user_id:chararray ...)
static_data = LOAD ... AS (req_user_id:chararray
required_data = JOIN input_data BY useriD, static_data BY req_user_id USING 'replicated';
required_data_fmt = -- project required fields.
I was not able to figure out how to do this in memory
So as per Murali's suggestion I added the user ids in a file..load the file and then do a join...that worked as expected for mr

Nhibernate and like statement on XML field

I have a wrapped fluent nhibernate framework that I'm reusing and have no control over the actual mapping.
In my entity object I have a property mapped as string to an XML column in sql.
Hence when I run a query like:
var myResult = (from myTable in DataManager.Session.Query<Table>()
where myTable.thatXmlFieldWhichIsMappedAsString.Contains(AnXmlSnippet))
select myTable).FirstOrDefault();
It is trying to use the LIKE operator in SQL which is invalid on that column type.
How can I get around this without having to select all the rows and converting to List first?
In case, that we do not need .Query() (LINQ), and we can use Criteria query or QueryOver, we can use conversion:
// the projection of the column with xml
// casted to nvarchar
var projection = Projections
.Cast(NHibernateUtil.StringClob
, Projections.Property("thatXmlFieldWhichIsMappedAsString"));
// criteria filtering with LIKE
var criteria = Restrictions.Like(projection, "searched xml");
// query and result
var query = session.QueryOver<MyEntity>()
.Where(criteria)
;
var result = query
.SingleOrDefault<MyEntity>()
;
From my experience this could lead to conversion into small nvarchar(255) - sql server... Then we can do it like this:
var projection = Projections
.SqlProjection("CAST(thatXmlFieldWhichIsMappedAsString as nvarchar(max)) AS str"
, new string[]{}
, new NHibernate.Type.IType[]{}
);

Convesion from Hive to PigLatin

I am trying to convert the below Hive statement to Pig:
max(substr(case when url like 'http:%' then '' else url end,1,50))
My pig statement for the above is:
url_group = GROUP data by (uid);
max_substr_url= FOREACH url_group generate SUBSTRING(MAX(((Coalesce(data.url) matches '.*http:%.*') ? '' : Coalesce(data.url))), 0, 49);
For some of the data, the url can be null. So I have written a pig UDF called Coalesce(String) which returns an empty string if the data is either null or empty. If the data is not null or not empty it returns the string back.
The above pig statement is giving me lot of trouble and tried n different options/ways but nothing worked. Anyone got any ideas on how to implement this? Please help me.
Thanks in advance
You are going to want to use a nested FOREACH so that you can do the substring transformation on each tuple in the data bag then take the MAX of the transformed bag.
A = GROUP data by (uid);
B = FOREACH url_group {
-- MAX needs a one column bag
transformed = FOREACH data
GENERATE SUBSTRING((Coalesce(url) matches '.*http:.*' ? '' : Coalesce(url)), 0, 49);
GENERATE group AS uid, MAX(transformed) ;
}