cancel
Showing results for 
Search instead for 
Did you mean: 

Alternative to PATH queries?

lyamamot
Champ in-the-making
Champ in-the-making
I read on the Search wiki page that:
Please note: Path queries will be extremely slow if there are more than a few dozen nodes in the result (even if other parts of the query, for instance on the cm:name, will limit the final result to a single node). Therefore, they should be avoided on large repositories, if at all possible.
Since this is the case, what is a good alternative to PATH queries? What is an efficient query to find all nodes under a particular hierarchy of a specific type with specific property values?

Edit: My last question is awkwardly worded. "What is an efficient query to find all nodes of a specific type that exist under a particular hierarchy, where each node has a specified property value. e.g. Find all cm:content files under Data Dictionary where the value of the title property is [some_title_value]?"
4 REPLIES 4

daniel_gradecak
Confirmed Champ
Confirmed Champ
We also noticed this and it seems that the change of the wiki was done 3 months ago. We would also like to know what is the preferred solution for such queries.

http://wiki.alfresco.com/w/index.php?title=Search&diff=prev&oldid=25650

dgenard
Champ on-the-rise
Champ on-the-rise
Hi,
do you have some more information about this performance issue ?
Which Alfresco release is concerned ?
Any alternative for PATH queries ?

Denis

tonc
Champ on-the-rise
Champ on-the-rise
Hi all,
I have exactly the same question…

Does anyone allready have a solution?

Thanks!

Toon

dbachem
Champ in-the-making
Champ in-the-making
Hi Guys!

Month ago we tried to get along with Path queries to filter our content by categories. This very fast endend in a performance desaster. So i switched to search category noderefs in the "@cm:categories" field. This is very fast, even if you have large amounts of filter-categories in your query, lets say 20 categories combined with AND/OR, nested in ():

(@cm:\categories:"workspace://SpacesStore/[cat1]" OR @cm:\categories:"workspace://SpacesStore/[cat2] OR …")

I also found out, that the LuceneCategoryServiceImpl (http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/repository/source/jav...) uses a slow PATH query expression to fetch category children. Thus i optimized this implementation by specializing the service:


import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.impl.lucene.LuceneCategoryServiceImpl;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.RegexQNamePattern;

/**
* @author dbachem
*/
public class LuceneCategoryServicePatch extends LuceneCategoryServiceImpl {

   private NodeService publicNodeService;

   private TenantService tenantService;

//   private Logger logger = Logger.getLogger(LuceneCategoryServicePatch.class);

   /**
    * just call the super constructor.
    */
   public LuceneCategoryServicePatch() {
      super();
   }

   /**
    * Set the node service
    *
    * @param publicNodeService
    */
   public void setPublicNodeService(NodeService nodeService) {
      this.publicNodeService = nodeService;
      super.setPublicNodeService(nodeService);
   }

   /**
    * Set the tenant service
    *
    * @param tenantService
    */
   public void setTenantService(TenantService tenantService) {
      this.tenantService = tenantService;
      super.setTenantService(tenantService);
   }


   /*
    * (non-Javadoc)
    *
    * @see
    * org.alfresco.repo.search.impl.lucene.LuceneCategoryServiceImpl#getChildren
    * (org.alfresco.service.cmr.repository.NodeRef,
    * org.alfresco.service.cmr.search.CategoryService.Mode,
    * org.alfresco.service.cmr.search.CategoryService.Depth)
    */
   @Override
   public Collection<ChildAssociationRef> getChildren(NodeRef categoryRef,
         Mode mode, Depth depth) {

//      logger.debug("categoryRef: " + categoryRef.toString());
//      logger.debug("mode:  " + mode);
//      logger.debug("depth: " + depth);

      // some validation
      if (categoryRef == null) {
         return Collections.<ChildAssociationRef> emptyList();
      }
      categoryRef = tenantService.getName(categoryRef);

      // get subCategories from NodeService; otherwise use Lucene (super.getChildren(..))
      if (mode == Mode.SUB_CATEGORIES) { //
         // logger.debug("PATCH: obtain subcategories from NodeService instead of Lucene");
         Collection<ChildAssociationRef> result;
         if (depth.equals(Depth.IMMEDIATE)) {
            result = publicNodeService.getChildAssocs(categoryRef,
                  ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL);
         } else {// depth.equals(Depth.ANY)
            result = new LinkedHashSet<ChildAssociationRef>();
            collectSubCategoriesDeep(categoryRef, result);
         }
         // logger.debug(" –> subcategories: " + result.size());
         return result;
      } else {
         return super.getChildren(categoryRef, mode, depth);
      }
   }

   private void collectSubCategoriesDeep(NodeRef categoryRef,
         Collection<ChildAssociationRef> container) {
      Collection<ChildAssociationRef> results = publicNodeService.getChildAssocs(
            categoryRef, ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL);
      for (ChildAssociationRef childAssocRef : results) {
         container.add(childAssocRef);
         collectSubCategoriesDeep(childAssocRef.getChildRef(), container);
      }
   }

}

Note that you must change your spring bean config to use this optimized impl. At the end you will have a solution which mostly avoids to use the slow PATH queries!