Dear Community,
I am working with automations and currently stumped by a seemingly simple problem that I can find no working solution for. I am building an automation that looks up objects and returns the "fullest" object(s) judging by attributes counted. I will first provide the steps of what I am doing followed by where I run into a problem and what I have already tried:
Object type: MyObjects
> Objects of this type can have a varying number of entries contained in their attributes. The main assumption is: "The more attribute entries an object contains, the more relevant it becomes as a query result".
MyObject Attributes:
- Key (must be filled and limited to 1 entry, must be unique)
- Name (must be filled and limited to 1 entry, must be unique)
- A1 (can be empty, can have multiple entries)
- A2 (can be empty, can have max. 1 entry)
- [...]
Query: Some Query that returns multiple objects from type MyObjects.
Output: {{LookupObjects}} with SmartObjects represented by tag. For example "KEY-1, KEY-4, [...], KEY-12"
> List of Asset-Objects matching some search criteria gets filled into {{LookupObjects}}
Smart Value: {{#lookupObjects.attributes}}{{size.asNumber}},{{/}}
> count of "how mighty" each object is (how many filled attributes it contains). Output e.g. "12,13,12,10,12,[...],12,"
Smart Value: {{CountFilledAttributes.split(",").max}}
> Returns the maximum Number from the previous list. Output e.g. "13"
Smart Value: {{#lookupObjects}}{{#if(equals(attributes.size.asNumber, $AttributeCountMax.asNumber))}}{{.}}, {{/}}~{{/}}
> Should make a list containing only objects that have the priviously found maximum number of attributes. "~" is contained for Debug porpuses, will be dropped in final iteration
Objects initially found: {{LookupObjects}} || Attribute Counts: {{CountFilledAttributes}} || Max Count: {{AttributeCountMax}} || Objects with Max Count: {{ObjectsWithMaxCount}}
For this example: {{ObjectsWithMaxCount}} does not work properly and returns only "~~~~[...]~"
In general: How do i get the smart object to use my smar variable {{AttributeCountMax}} while iterating over the listed items from {{LookupObjects}}? I know that there are threads close to this subject but I can't find any tackling this specific subject.
I am aware and confident that I could restructure this to run and work using custom branching and I will do so if actually necessary - even if it feels a bit inelegant (I strongly suspect it will result in quite a bit of additional runtime). I still pose this question as I would love to deepen my understanding about automation function behaviour here, please bear with me (and let me extend a big thanks at everyone helping me here).
> returns the expected result. e.g. "~KEY-4,~~[...]~
> returns incorrect result. e.g. "~~~[...]~". Kind of expected because "AttributeCountMax" obviously does not exist as an Attribute on the asset objects so NULL would be returned, making the equals logic false on every comparison. (I checked if it would return all items if I would change attributes.size.asNumber into something that returns NULL and sure enough: All items from the list DID get returned.)
> (expectedly) doesn't render. Automation hates nested curvy brackets
> doesn't render, $ doesn't seem make nested curvy brackets more palatable to our poor little automation.
> doesn't render, automation also seems to hate random brackets
> returns incorrect result. e.g. "~~~[...]~"
> returns incorrect result. e.g. "~~~[...]~"
> returns incorrect result. e.g. "~~~[...]~". At this point i am running out of ideas and I am gennerally unsure if the $ even does anything.
I feel like i am missing just one syntax detail and I will be greatly thankful for any suggention and educational content on this matter.
Kind regards,
Ludwig
EDIT: fixed some typos
Hey @Ludwig Einicke ,
I found a solution to my problem and I think it could be a solution to yours too.
First of all, I'm telling you that's it's not the prettiest solution like you probably expected, but it works for me, so I hope it'll work for you too.
What you should do is actually to create an artificial loop by stacking loop actions one after the other and then call automation to itself using webhook, again and again.
If you do it right, you could squeeze many iterations within a single rule, which will save you a bunch of rule runs.
For example, in my case, I had to update object attribute on my asset object in a way that will remove only selected objects from the attribute and leave the rest intact.
I made this possible by using 2 automation rules, because first one is triggered by field value changed and the second one is triggered by a web hook.
So the first one goes through objects and can resolve for up to 10 objects, and if more than that is selected, the second rule is called.
Second rule can also handle 10 objects, and if that's not enough it'll call itself again until everything is done.
My process could be even more optimized by removing some unnecessary log actions which could give me some more space for more useful actions and allow me even more than 10 objects within single rule run.
I will try to give you example with your case.
You have 2 key variables:
count of objects and numbers is the same. For example:
example variable1 object keys: KEY-123, KEY-234, KEY-345, KEY-456
example variable2 number of object attributes: 5, 8, 7, 4
so 4 keys and 4 count numbers - positions match.
Using first() smart value, you can always extract one, exact position from each variable.
First, find the max number of attributres (in this case 8 ).
Then use first() function to extract 5 from variable2. Use IF to check if current item is equal to max number.
User remove() or left, right function to remove 5 from the list. Then repeat the same for 8, 7, 4...
use IFs in between to check if you found the right number to "stop" the loop, and at the end you can use a web hook to call the rule again.
I used issue properties to store data in between rule runs.
Here is image of my rule.
logs:
it's a bit complex to explain it in this way, but I hope you got the point.
The whole point is in creating a fake loop (manual loop) and use IF's and functions like first, remove, trim... to edit lists of objects, elements, numbers, whatever and then take out only those you need.
Regards,
Benjamin
Hey @Benjamin Črnjak,
thank you for the extensive response! I can see how much work got poured into this solution. I like the general concept of accessing issue properties as it provides another puzzle piece to semi-temporarily store information from functions/loops. Can you tell me why you have added a delay-block in the middle of your automation? Have you had experiences with smart branching? It looks like your solution could be implemented that way (IF branches get processed sequentially instead of simultaneuos), have you tried that or experienced trouble with the branching?
During my tests I have been wondering if I am approaching this from the completely wrong direction. If AQL is close enough to SQL there should be a way a use the "ORDER BY" part or the Asset-Query to automatically order by Attributes.size. This would spare a lot of trouble because I would be able to simply pick the first object from LookupOjects AND have a way lower runtime on top. Let's hope this works. Unfortunately initial results from looking into the AQL documentation do not look too promising.
Kind Regards,
Ludwig
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
hey @Ludwig Einicke ,
I'm not 100% sure right now, because I did a lot of testing to pull this out. I think that delay block in the middle was there before in one of the tests. I think it's not needed actually and you can skip it.
As of AQL similarity to SQL, unfortunately, I think you won't be able to get order of objects based on attributes number.
regards,
Benjamin
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Ludwig Einicke , welcome to the community! 😊
We are happy to have you here. 😉
I've recreated your automation rule and tried with multiple different approaches. It seems that Jira automation won't recognize smart value inside nested functions or more likely, inside lookup object list with nested functions inside IF.
Because everything works before that, all variables are correct and available, but it doesn't work except with a branch.
Here is a branch I made and it returns correct results:
Create an advance branch against lookupobjects smart variable.
Then add IF as displayed on image above.
Print object if true.
Here are results:
I know you said you would like to avoid branch because of execution time, but unfortunately, I wasn't able to find better solution.
Hope this helps.
Regards,
Benjamin
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello and thank you for the warm welcome Benjamin,
it definitely comes as a surprise to me that there is no way to tell a function "hey, you have to look into the defined variables to find this". This was before I dug around a little and found out that it is all a matter of perspective: From what I have found we can consider ourselves lucky that smart values work for at least the usual cases without nested functions during list-per-object-operations. The functionality seems to have been added as recently as 2022/2023(!). Maybe there will be some "escape operator" in the future.
Back the to main topic: It seems I have to use what i wanted to conciously avoid. Advanced branching sets up a new challenge - I need to find a way to transition this sulution from writing into an audit log to returning a list that I can use to further search and sort the objects.
I am imagining something like creating a variable before the branching that gets read into a brach-only variable and rewritten with the added results during the branching. This could run into some trouble: Are the branches even happening sequentially or will this run into some parallel execution problem? I will run some tests and report back live from the battlefield.
Kind regards,
Ludwig
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Ludwig Einicke currently I can't provide you with good solution, as I'm looking for solution myself for very similar problem as yours.
If I find out something new, I'll inform you here.
regards,
Benjamin
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.