Support Questions

Find answers, ask questions, and share your expertise
Celebrating as our community reaches 100,000 members! Thank you!

Nifi expression language for loops over attributes

New Contributor

Currently I am having around 15 attributes in my flowfile. Out of these 15, i only want a few (all the attributes that have a prefix 'error_' in it. These 'error_*' attributes can have 2 sets of values, eighter- 'valid' or some error code, say- '945'. Now i want to iterate though all the attributes with prefix - 'error_' and if its value is 'valid', do nothing and if its value is having some error code, append the error code to a string separated by ';'. So basically, if I have 5 error_ attributes:

error_field1: '123'
error_field2: 'Valid'
error_field3: '567'
error_field4: 'Valid'
error_field5: '45'

I want my output as - '123;567;45'.

Please help me as i am new to Nifi and i am not sure on how to work with such complex EL.


Master Collaborator


Sorry, I can't give you a perfect solution but maybe a hint to find one.
Just do GenerateFlowFile and set your attributes like in your example.
Then take UpdateAttribute and play around with Expression Language possibilities like "anyMatchingAttribute" or "allMatchingAttribute" maybe in combination with "join".

Have a look in the documentation here

Expert Contributor

Hi @Nidutt! Use the below Expression Language:

${literal(${allMatchingAttributes("error_field.*"):join(";")}):replaceAll('Valid|;',' '):trim():replaceAll('\s+',';')}


Master Collaborator


Great solution! I was sure it has to be possible but couldn't find out how...


Just for my understanding:
First all attributes name starting with error_field getting joined and then you replace the value 'Valid' with space and removing this by the last replaceAll.

But what is the meaning of | here: replaceAll('Valid|;',' ')
Without | the result is 123;;567;45 but why not 123;;567;;45


Thanks in advance for reply.

Expert Contributor


If you consider various use cases,

1)Consider the input 123;Valid;567;45. The first replace method ( replaceAll('Valid',';') ) will give 123; ;567;45 which on applying the next replace method ( replaceAll(' ',';') ) will give 123;;567;45. This is not the desired output.

2)Consider another input Valid;123;567;Valid;Valid;45. First replace method will give  ;123;567; ; ;45
Second replace method will give ;;123;567;;;45. Again, this is not the desired output.


To remove all the confusion, what I wanted to do was, separate all the values other than "Valid" with empty spaces. So, I replaced Valid and ; with empty spaces.

But, there might be cases where there are empty spaces at the beginning or at the end ( ( 123 567 45) or (123 567 45 )). So, I used trim method to remove outer spaces. Then, you will be left with values other than "Valid" separated by spaces (can be more than 1). So, now, the second replace method will just add one semi-colon, irrespective of the number of spaces between. So, the output will be 123;567;45.
Hence, the regex Valid|; will replace both "Valid" and semi-colons.

Master Collaborator


OK, it covers possible alternative cases.
Got it! Thanks for this explanation.