How to optimize IQL “HAVING outboundReferences()”​ queries in Groovy scripts (Jira, Insight)

Jira Server / Data Center

IQL queries work really slow in Groovy scripts

It was quite strange for me, that IQL queries wich contain outboundReferences() functions work quite fast in the IQL searcher, but work extremely slow in Grovy scripts. Many times we have to get some Insight objects and use it in post-functions, REST Endpoints etc.

What we have got?

  1. We have got a list of the Insight objects as a List<ObjectBean>. Let’s call it objectsForLoop.
  2. We have got a list of all Insight objects which could be used as inbound references. All of them are the children of the Object Type “sample”.
  3. Each element of the objectsForLoop contain zero, one or more inbound references to elements to another Insight objects.
  4. We would like to print or list all elements from objectsForLoop with inbound references.

HAVING outboundReferences()

The easiest way to print all insight objects and its inbound references seems to be an IQL query. We can use it during iteration of the objectsForLoop list. I have got about 10000 objects and 60 possible references. In my case, script executing took more than 3 minutes!

Groovy
import com.atlassian.jira.component.ComponentAccessor;

// get the Insight class
Class iqlFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.IQLFacade");
def iqlFacade = ComponentAccessor.getOSGiComponentInstanceOfType(iqlFacadeClass);

// get the 'objectsForLoop' list
def objectsForLoop = iqlFacade.findObjectsByIQLAndSchema(<schema_id>, <IQL query>);

objectsForLoop.each() {
  object ->
    // find all references wich exist as outboundReferences in the current object
    def references = iqlFacade.findObjectsByIQLAndSchema(<schema_id>,  "objectTypeId IN objectTypeAndChildren(\"sample\") AND object HAVING outboundReferences(Key = object.getKey()");

    // some code.....
    // references => objects where the current object exists as outbound reference
    // object => current object from iteration
}

My solution

Inbound and outbound references are very deeply nested. At the first, we should get ObjectAttributeBeans from the object, then ObjectAttributeValueBeans. Ids of the references exist as ObjectAttributeValueBeans values. It looks little complicated, but I try to check how it works. I was suprised becauce executing took 1.7 seconds only.

Groovy
import com.atlassian.jira.component.ComponentAccessor

// get the Insight class
Class iqlFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.IQLFacade");
def iqlFacade = ComponentAccessor.getOSGiComponentInstanceOfType(iqlFacadeClass);

// get the 'objectsForLoop' list
def objectsForLoop = iqlFacade.findObjectsByIQLAndSchema(<schema_id>, <IQL query>);

objectsForLoop.each() {
  object ->
    // find all possible outboundReferneces
    def references = iqlFacade.findObjectsByIQLAndSchema(<schema_id>,  "objectTypeId IN objectTypeAndChildren(\"sample\")");

  List referencesFromObject = new ArrayList<>();
  references.each(){
    reference ->
      reference.getObjectAttributeBeans().each()  {
        referenceObjectAttributeBean ->
          referenceObjectAttributeBean.getObjectAttributeValueBeans().each()  {
           if (referenceObjectAttributeValueBean.getValue()==object.getId())
             referencesToAdd.add(reference);
          }
      }
   }

   references = referencesFromObject;
   // some code.....
   // references => objects where the current object exists as outbound reference
   // object => current object from iteration
};
Go to top