prolog
MySQL table name: ar_tmp has two columns id int and name int
to do
I execute sql
insert into ar_tmp (id, name) values (1, 4);
and CaptureChangeMySQL captures this CDC and flow-content like this
{
"type":"insert",
"timestamp":1550221517000,
"binlog_filename":"mysql-bin.013920",
"binlog_position":241518646,
"database":"platform_data",
"table_name":"ar_tmp",
"table_id":2899035,
"columns":[
{
"id":1,
"name":"id",
"column_type":4,
"value":1
},
{
"id":2,
"name":"name",
"column_type":4,
"value":4
},
{
"id":3,
"value":4
}
]
}
But I want the result in this format
{
"type":"insert",
"timestamp":1550221517000,
"binlog_filename":"mysql-bin.013920",
"binlog_position":241518646,
"database":"platform_data",
"table_name":"ar_tmp",
"table_id":2899035,
"columns":[
{
"id":1,
"name":4
}
]
}
or
{
"id":1,
"name":4
}
solution
It can be done by hard coding using jsonPath function
But maybe to 'hard' to do this because each column using the same code which making the processor redundance(say 50 columns). Worsely, it's danger when the column name changed.
Any ideas?
JoltTransformJSON can help you here.
Try it out here
Jolt Spec for your demo input json:
[
{
"operation": "shift",
"spec": {
"columns": {
"*": {
"value": "columns.#(1,name)"
}
},
"*": "&"
}
}
]
The result is:
{
"type" : "insert",
"timestamp" : 1550221517000,
"binlog_filename" : "mysql-bin.013920",
"binlog_position" : 241518646,
"database" : "platform_data",
"table_name" : "ar_tmp",
"table_id" : 2899035,
"columns" : {
"id" : 1,
"name" : 4
}
}
Related
Hi pls help with this jolt transformation.
Note:
If Environment exists then add new field numid and value is 1
If costcenter exists then add new field numid and the value is 2
Input:
[
{
"Environment": "net",
"BillingProfileId": 863,
"ms-resource-usage": "azure-cloud-shell"
},
{
"CostCenter": "check",
"BillingAccountName": "HCL Technologies Ltd.",
"ServiceFamily": "Compute"
}
]
Expected output:
[
{
"Environment": "net",
"numid": "1"
"BillingProfileId": 863,
"ms-resource-usage": "azure-cloud-shell"
},
{
"CostCenter": "check",
"numid" : "2",
"BillingAccountName": "HCL Technologies Ltd.",
"ServiceFamily": "Compute"
}
]
Thanks
You can use this spec:
[
{
"operation": "shift",
"spec": {
"*": {
"#": "[&1]",
"Environment": {
"#1": "[&2].numid"
},
"CostCenter": {
"#2": "[&2].numid"
}
}
}
}
]
how to convert the following data
{
"name" : "abcd",
"middleName" : "srivastav"
}
into
{
"name" : "abcd",
"middleName" : "srivastav"
"id" : "abcd"
}
by using a jolt transform such that the id and the name are within the same object as the expected output.
modify-default-beta or default operations will work for this :
[
{
"operation": "modify-default-beta",
"spec": {
"id": "abcd"
}
}
]
One option is to replicate the value of name through use of "#(0,name)": while keeping the current attributes by "*": "&" notation within a shift transformation such as
[
{
"operation": "shift",
"spec": {
"*": "&",
"#(0,name)": "id"
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is
or another option is to use a modify(overwrite/default) transformation to dynamically replicate the value of name attribute for id such as
[
{
"operation": "modify-overwrite-beta",
"spec": {
"id": "#(1,name)"
}
}
]
the second demo is
I need to add this attribute named 'metadata' to json flow content.
The attribute 'metadata' is like:
{"startTime":1451952013663, "endTime":1453680013663, "name":"Npos19", "deleted":false}
The input is like this:
{
"id": 154299613718447,
"values": [
{
"timestamp": 1451977869683,
"value": 13.1
},
{
"timestamp": 1453949805784,
"value": 7.54
}
]
}
My goal is like:
{
"id": 154299613718447,
"values": [ {
"startTime":1451952013663,
"endTime":1453680013663,
"name":"Npos19",
"deleted":false,
"timestamp": 1451977869683,
"value": 13.1
},
{
"startTime":1451952013663,
"endTime":1453680013663,
"name":"Npos19",
"deleted":false,
"timestamp": 1453949805784,
"value": 7.54
}
]
}
I tried to use the Jolt Transformation:
{
"operation": "default",
"spec": {
// extract metadata array from json attribute and put it in a temporary array
"tempArray": "${metadata:jsonPath('$.*')}"
}
}
but it does not work. I need to extract metadata array with $.* because I do not know what keys will be present.
Is there an alternative fast way with other nifi processors to merge the attribute with flow content?
thanks in advance
It's possible with combination of two processors: EvaluateJsonPath ->ScriptedTransformRecord.
EvaluateJsonPath
Destination: flowfile-attribute
Return Type: json
values (dynamic property): $.values
ScriptedTransformRecord
Record Reader: JsonTreeReader
Record Writer: JsonRecordSetWriter
Script Language: Groovy
Script Body:
def mapMetadata = new groovy.json.JsonSlurper().parseText(attributes['metadata'])
def mapValue = new groovy.json.JsonSlurper().parseText(attributes['values'])
def values = mapValue.each { value ->
mapMetadata.each { k, v ->
value."${k}" = v
}
}
record.setValue('values', null)
record.setValue('updateValues', values)
record
Output json
[ {
"id" : 154299613718447,
"values" : null,
"updateValues" : [ {
"timestamp" : 1451977869683,
"value" : 13.1,
"startTime" : 1451952013663,
"endTime" : 1453680013663,
"name" : "Npos19",
"deleted" : false
}, {
"timestamp" : 1453949805784,
"value" : 7.54,
"startTime" : 1451952013663,
"endTime" : 1453680013663,
"name" : "Npos19",
"deleted" : false
} ]
} ]
I need to create a JSON array in order to split it into several jobs with Nifi.
The array needs to be created based on an existing array inside the JSON.
Can't figure out how to dynamically create a reference to another object in the JSON. I want the reference "#(2,#)" to work, but this is not supported.
INPUT
{
"name": "Loki",
"id": "1234",
"loc": "Utgard",
"age": "unknown",
"listitems": [
"name",
"id"
]
}
SPEC (that doesn't work):
[
{
"operation": "shift",
"spec": {
// Loop all listitems
"listitems": {
"*": {
// Get the value of the current item and push to processlist.type array
"#": "processlist[#2].type",
// Here is the problem, I need to get the "top level" value for the current value/key
"#(2,#)": "processlist[#2].value"
}
}
}
}
]
Expected output:
{
"processlist" : [
{
"type" : "name",
"value" : "Loki"
}, {
"type" : "id",
"value" : "1234"
}
]
}
SPEC (that will run but is not correct)
[
{
"operation": "shift",
"spec": {
// Loop all listitems
"listitems": {
"*": {
// Get the value of the current item and push to processlist.type array
"#": "processlist[#2].type",
// Here is the problem, I need to get the top level value for the current value/key
// Forcing this to "name" will at least execute the code
"#(2,name)": "processlist[#2].value"
}
}
}
}
]
Any ideas?
You can proceed one more step by adding "*" key to nest the current spec more while roaming by #(3,&) dynamically as this ampersand represents the incurred key values name and id such as
[
{
"operation": "shift",
"spec": {
"listitems": {
"*": {
"*": {
"#1": "processlist[#3].type",
"#(3,&)": "processlist[#3].value"
}
}
}
}
}
]
I have Json array with each of its object having dynamic attributes. I have to merge all the object into one Json object in nifi with common attribute's value concatenated and other attributes as it is.
I have already tried following spec, and it is giving common attributes as array list. But I want that common attribute's value to be concatenated and I don't know how to do that. Any suggestion would be really helpful. Thanks in advance.
[
{
"operation": "shift",
"spec": {
"*": {
"*": "&"
}
}
}
]
The input is like( NOTE: The attributes are dynamic so not sure always going to have these attributes)
[
{
"firstName": "Sam1",
"lastName": "Achom1",
"place": "Silchar1"
},
{
"firstName": "Saya2",
"lastName": "Singh2",
"place": "Macherial2",
"Second1stAttribute": "SomeValue"
},
{
"firstName": "Sam3",
"lastName": "Achom3",
"place": "Silchar3",
"Third2ndAttribute": "SomeValue2"
}
]
The output I am getting with before mentioned spec
{
"firstName" : [ "Sam1", "Saya2", "Sam3" ],
"lastName" : [ "Achom1", "Singh2", "Achom3" ],
"place" : [ "Silchar1", "Macherial2", "Silchar3" ],
"Second1stAttribute" : "SomeValue",
"Third2ndAttribute" : "SomeValue2"
}
And Expecting the output as
{ "firstName" : "Sam1 Saya2 Sam3",
"lastName" : "Achom1 Singh2 Achom3",
"place" : "Silchar1 Mancherial2 Silchar3",
"Second1stAttribute" : "SomeValue",
"Third2ndAttribute" : "SomeValue2"
}
You can "join" the items from your arrays. This spec will do the trick:
[
{
"operation": "shift",
"spec": {
"*": {
"*": "&"
}
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"*": "=join(' ',#(1,&))"
}
}
]