Groovy Script AEM Asset Reference Update

796 views Asked by At

So I'm working with AEM and am attempting to create a script that grabs all pages under a specific path and updates the image reference on the page from a list of assets under a curtain path.

Both of my select query's aren't returning the specific pages and assets I need.

I'm also getting an error that my queries are searching over 100000 Nodes

How can i resolve this error and query my resources better?

import com.day.cq.wcm.api.Page
import javax.jcr.query.Query
import javax.jcr.query.QueryManager
import org.apache.sling.api.resource.ModifiableValueMap

import groovy.transform.Field


static void main(String[] args) 
{

String[] assetNodes
String[] pageNodes

String pagePath ="/content/we-retail/us/en"
String pageResourceType = "weretail/components/structure/page"
String assetPath ="/content/dam/microsoft/internal/en"
String assetQuery = "b1048291-23fa-422a-a7c4-9ea4bae0effc"
boolean isAsset = true;
pageNodes = GetResourcePath(pagePath, pageResourceType);

assetNodes = GetRosourceAsset(assetPath, assetQuery);

InputAssetsOnPage(pageNodes,assetNodes);
} 


//Find the Node paths for all Pages to modify 
//Narrow down to image component

def GetResourcePath(String rootPath,String queryParam)
{
    int i = 0
   def String[] allNodes = new String[500]

    Page page = getPage(rootPath)

def queryManager = session.workspace.queryManager;
def param= queryParam;
def statement = 'select * from nt:base where jcr:path like \''+page.path+'/%\' and sling:resourceType = \'' + param + '\'';

Query query=queryManager.createQuery(statement, 'sql');

final def result = query.execute()

println "Total pages found = " + result.nodes.size();

NodeIterator nodeIterator = result.getNodes();

while(nodeIterator.hasNext())
{
    def hitNode = nodeIterator.nextNode();
    allNodes[i] = hitNode.getPath();
    i++;

}
println allNodes

return allNodes;
}


//Find all assets paths to add to page 
def GetRosourceAsset(String rootPath,String queryParam)
{
   int i = 0
   def String[] allNodes = new String[500]

    Page page = getPage(rootPath)

def queryManager = session.workspace.queryManager;
def param= queryParam;
def statement = 'select * from nt:base where jcr:path like \''+rootPath+'/%\'';
Query query=queryManager.createQuery(statement, 'sql');

final def result = query.execute()

println "Total Assets found = " + result.nodes.size();

NodeIterator nodeIterator = result.getNodes();

while(nodeIterator.hasNext())
{
    def hitNode = nodeIterator.nextNode();
    allNodes[i] = hitNode.getPath();
    i++;

}
println allNodes

return allNodes;
}

//Modify image component property with unique asset path 
void InputAssetsOnPage(String[]pageRefrence, String[]assetRefrences)
{
String[] nodes= pageRefrence;
String[] assetNodes = assetRefrences;

nodes.eachWithIndex { self,i->

    javax.jcr.Node node=getNode(nodes[i])

    ModifiableValueMap mVMap=resourceResolver.resolve(node.path).adaptTo(ModifiableValueMap.class);

    mVMap.put("fileRefrence", assetNodes[i]);

    println "Property modified to "+node.path;

    println "Dry Run "+data.dryRun;

    if(!data.dryRun) {
        session.save();
    }
}

}
//Save session
1

There are 1 answers

0
Alexander Berndt On

For mass-updates it is very likely to target too many nodes. You have to try some approaches, to either get just under the limit - or change you approach.

First select pages from cq:PageContent, instead from nt:base. The query-indexes are organised by jcr:primaryType. The nt:base index contains everything. So there are much more nodes.

Second use SQL-2 and ISDESCENDANTNODE() instead of a like operator. I don't expect the like-operator to be so specific. But, if you query almost all pages anyway - it won't help much.

Third iterate over parts of you page-tree. Then the remaining subtree is much small, can can be queried.

  • For a mass-update, which probably touches more than 15% of your pages, then just iterate over all pages. Don't forget to commit from time to time. (e.g. every 100 changes)

Code sample to iterate a page-tree

def rootPage = getPage("/content/uac/glooly/es")
rootPage.recurse() { page ->
   println(page.path)
   fixAssetsOnPage(page)
}
  • You can iterate over the first n levels over the content tree, and then deep dive with a query. So you could have less than 100.000 image components

Code sample to iterate over first 2 levels, and then query:

def rootPage = getPage("/content/we-retail/us/en")
rootPage.iterator().each { firstLevelPage ->
   firstLevelPage.iterator().each { secondLevelPage ->
      println(secondLevelPage.path)
      queryAndFixAssets(secondLevelPage)
      save()
   }
}

Fourth create an oak:index for you query. Especially if you could use it for later too. But in your case there is an existing index for sling:resourceType, which should be could enough. You have just too many hits.

PS: You probably don't need to query pages. Just query the image components in a small enough subtree. But we can't see that from you code sample.