How to use jolt to parse array of array - arrays

I want to use jolt to parse the json. But I can't get the age value in the first level successfully. May someone help me?
The input json is like this:
{
"name": "abc",
"age": "20",
"Photos": [
{
"a": "AAA.jpg",
"b": "BBB.jpg",
"XXX123": [
{
"v1": "AAA.jpg",
"v2": "BBB.jpg"
}
]
}
]
}
My Spec:
[
{
"operation": "shift",
"spec": {
"Photos": {
"*": {
"XXX123": {
"*": {
//"*": "&2.[&1].&",
"#(2,a)": "&2.[&1].a",
"#(2,b)": "&2.[&1].b",
"#(3,age)": "&3.[&1].age"
}
}
}
}
}
}
]
The output I want:
{
"XXX123" : [ {
"a" : "AAA.jpg",
"b" : "BBB.jpg",
"age" : "20"
} ]
}

Spec
[
{
"operation": "shift",
"spec": {
"Photos": {
"*": {
"XXX123": {
"*": {
//"*": "&2.[&1].&",
"#(2,a)": "&2.[&1].a",
"#(2,b)": "&2.[&1].b",
"#(4,age)": "&2.[&1].age"
}
}
}
}
}
}
]
You were close.
"#(3,age)": "&3.[&1].age"
needed
"#(4,age)": "&2.[&1].age"
From where that line was you needed to go up the tree 5 levels.
Counting from Zero
0 -> "*"
1 -> "XXX123"
2 -> "*"
3 -> "Photos"
4 -> your top level input
then lookup "age" in the top level map

Related

Looping through multiple line items in a single array output in JOLT

I want to write a Jolt definition that loops through each object in my attachment array, and move the object to the data array. At the same time, it should map single object attachment nest, and move the object to the data object.
Currently my spec below is working when my attachment block is an array.
Input :
{
"IntegrationEntities": {
"integrationEntity": [
{
"integrationEntityHeader": {
"attachments": {
"attachment": [
{
"name": "EV10044.docx"
},
{
"name": "Test1.txt"
}
]
}
}
}
]
}
}
JOLT Spec :
[
{
"operation": "shift",
"spec": {
"IntegrationEntities": {
"integrationEntity": {
"*": {
"integrationEntityHeader": {
"attachments": {
"attachment": {
"*": {
"name": "data[&1].filename"
}
}
}
}
}
}
}
}
}
]
Current Output :
{
"data": [
{
"filename": "EV10044.docx"
},
{
"filename": "Test1.txt"
}
]
}
I want to handle the scenario in a way where regardless if the attachment is an array or object it should give the input. Currently it fails if the attachment block is an object and gives the output as NULL.
IF Input is:
{
"IntegrationEntities": {
"integrationEntity": [
{
"integrationEntityHeader": {
"attachments": {
"attachment": {
"name": "EV10044.docx"
}
}
}
}
]
}
}
Desired Output:
{
"data": {
"filename": "EV10044.docx"
}
}
You can use this spec:
[
{
"operation": "shift",
"spec": {
"IntegrationEntities": {
"integrationEntity": {
"*": {
"integrationEntityHeader": {
"attachments": {
"attachment": {
"name": "data.filename",
"*": {
"name": "data[&1].filename"
}
}
}
}
}
}
}
}
}
]
I just added the below line to your spec. So if you have name in the attachment it is assumed that you have 1 attachment. If no name is found it is assumed you have an array and your other codes is correct.
"name": "data.filename",
An option is to use a shift transformation spec in which the objects are qualified by path expressions and the arrays are constructed along with sub-indexes by symbolic expression "*": { such as
[
{
"operation": "shift",
"spec": {
"#IntegrationEntities.integrationEntity": {
"*": { // indexes of the array
"#integrationEntityHeader.attachments.attachment": {
"*": { // indexes of the array
"*": "data[].file&", // if "attachment" is an array
"#1,name": "data.file&" // if "attachment" is an object
}
}
}
}
}
}
]
Btw, if you didn't need to rename the innermost attribute name to fieldname, the following shorter spec would suffice :
[
{
"operation": "shift",
"spec": {
"#IntegrationEntities.integrationEntity": {
"*": {
"#integrationEntityHeader.attachments.attachment": "data"
}
}
}
}
]

Mongo Query to modify the existing field value with new value + array of objects

I want to update many documents based on the condition in MongoDB.
MODEL is the collection which has the document with below information.
"info": [
{
"field1": "String1",
"field2": "String2"
},
{
"field1": "String1",
"field2": "String_2"
}
],
"var": "x"
I need to update all the "String1" value of field1 with "STRING_NEW". I used the below query to update but not working as expected.
db.model.updateMany(
{ "info.field1": { $exists: true } },
[
{ "$set": {
"info": {
"$map": {
"input": "$info.field1",
"in": {
"$cond": [
{ "$eq": ["$$this.field1", "String1"] },
"STRING_NEW",
$$this.field1
]
}
}
}
} }
]
)
Please have a look and suggest if anything is to be modified in the above query.
Solution 1
With the update with aggregation pipeline, you should iterate the object in info array and update the iterated object by merging the current object with new field1 field via $mergeObjects.
db.model.updateMany({
"info.field1": "String1"
},
[
{
"$set": {
"info": {
"$map": {
"input": "$info",
"in": {
"$cond": [
{
"$eq": [
"$$this.field1",
"String1"
]
},
{
$mergeObjects: [
"$$this",
{
"field1": "STRING_NEW"
}
]
},
"$$this"
]
}
}
}
}
}
])
Demo Solution 1 # Mongo Playground
Solution 2
Can also work with $[<identifier>] positional filtered operator and arrayFilters.
db.model.updateMany({
"info.field1": "String1"
},
{
"$set": {
"info.$[info].field1": "STRING_NEW"
}
},
{
arrayFilters: [
{
"info.field1": "String1"
}
]
})
Demo Solution 2 # Mongo Playground

how to create specific array in jolt

im in learning process to learn jolt, but quite hard to master as there is array and the output must be the exactly the same as example below.
how to create a jolt spec form ,
the json input is like this :
[
{
"encounter_date": "1616509603296",
"id_no": "671223025051",
"patient_id": "MAEPS-PID-2100003716",
"patient_mrn": "MAEPS-MRN-2100003815",
"first_name": "MOHD RAZALI "
},
{
"encounter_date": "1621324591194",
"id_no": "950224145647",
"patient_id": "MAEPS-PID-2100030302",
"patient_mrn": "MAEPS-MRN-2100030401",
"first_name": "MUHAMMAD FADDIL BIN YASIN"
}
]
expected output is like this :
{
"forms": [
{
"visit": {
"patientId": "MAEPS-PID-2100003716",
"Patientmrn": "MAEPS-MRN-2100003815",
"encounterDate": "2021-03-23 22:26:43.296"
},
"person": {
"firstname": "MOHD RAZALI ",
"identifications": [
{
"idNo": "671223025051"
}
]
}
},
{
"visit": {
"patientId": "MAEPS-PID-2100030302",
"Patientmrn": "MAEPS-MRN-2100030401",
"encounterDate": "2021-05-18 15:56:31.194"
},
"person": {
"firstname": "MUHAMMAD FADDIL BIN YASIN",
"identifications": [
{
"idNo": "950224145647"
}
]
}
}
]
}
i'm new to jolt and require guidance
This can be done with just a single shift operation as below.
[
{
"operation": "shift",
"spec": {
"*": {
"patient_id": "forms[&1].visit.patientId",
"patient_mrn": "forms[&1].visit.Patientmrn",
"encounter_date": "forms[&1].visit.encounterDate",
"first_name": "forms[&1].person.firstname",
"id_no": "forms[&1].person.identifications[0].idNo"
}
}
}
]

Is is possible to concatenate values from two different objects in Jolt

I would like to know if it is possible in Jolt to concatenate values from different objects. I've successfully concatenated "orderType" (value=ABC) and "minorCode" (value 0003) from the "orderInformation" object to create an output key of "Job.JobTypeCd" (value ABC0003). I would like to add the "serviceType" value as a prefix to that new key so the output value would be "123ABC0003".
Example input
{
"orderInformation": {
"orderType": "ABC",
"minorCode": "0003"
},
"account": {
"serviceType": "123"
}
}
Current Spec
[
{
"operation": "modify-default-beta",
"spec": {
"orderInformation": {
"JobType": "=concat(#(1,orderType),#(1,minorCode))"
}
}
},
{
"operation": "shift",
"spec": {
"orderInformation": {
"JobType": "Job.JobTypeCd"
},
"account": {
"serviceType": "Job.AddThisAsPrefix2JobTypeCd"
}
}
}
]
Current output
{
"Job" : {
"JobTypeCd" : "ABC0003",
"AddThisAsPrefix2JobTypeCd" : "123"
}
}
Desired output
{
"Job" : {
"JobTypeCd" : "123ABC0003"
}
}
You can include the serviceType value to the same concat operation as below.
"JobType": "=concat(#(2,account.serviceType),#(1,orderType),#(1,minorCode))"
Full spec
[
{
"operation": "modify-default-beta",
"spec": {
"orderInformation": {
"JobType": "=concat(#(2,account.serviceType),#(1,orderType),#(1,minorCode))"
}
}
},
{
"operation": "shift",
"spec": {
"orderInformation": {
"JobType": "Job.JobTypeCd"
}
}
}
]

jolt shift array up a level, but preserve the array even if empty

I struggled hard with how to title this one. This is from the twitter sample stream. I need the hashtag text pulled out into an array at the top level. I have that working, but if there is just one hashtag it jolt's to a single string, and if there are no hashtags (twitter gives back an empty array in that case), then the field disappears. I want to do the same thing with the URL field & user mentions.
Input JSON:
{"entities": {
"hashtags": [{"text": "somethingClever",
"indices": [22, 28]},
{"text": "somethingLessClever",
"indices": [30, 40]}],
"urls": [],
"user_mentions": [{
"screen_name": "username",
"indices": [3, 19]
}],
"symbols": []
}
Desired output:
{
"hashtags": ["somethingClever"],
"urls": [],
"user_mentions": ["username"]
}
But what I'm getting is this:
Actual output, note screen_name is not an array and urls is altogether missing. That is the crux of my problem.
{
"hashtag_text" : [ "somethingClever", "somethingLessClever" ],
"screen_name" : "username"
}
Here is my jolt spec so far:
[
{
"operation": "shift",
"spec": {
"entities": {
"hashtags": { "*": { "text": ".hashtag_text" } },
"urls": { "*": { "url_text": ".urls" } },
"user_mentions": { "*": { "screen_name": ".&" } }
}
}
}
]
I figured it out. I used shift to bring the necessary array elements to the next level up (from entities to root). Next I used the default operation to make it still be an array even if the array was empty. Lastly, I used the cardinality operation to make it be an array even if there is only one element.
Hopefully this helps somebody.
[
{
"operation": "shift",
"spec": {
"entities": {
"hashtags": { "*": { "text": ".hashtags" } },
"urls": { "*": { "url_text": ".urls" } },
"user_mentions": { "*": { "screen_name": ".&" } }
}
}
},
{
"operation": "default",
"spec": {
"hashtags[]": {},
"urls[]": {},
"screen_name[]": {}
}
},
{
"operation": "cardinality",
"spec": {
"hashtags": "MANY",
"urls": "MANY",
"screen_name": "MANY"
}
}
]

Resources