April 10, 2020
Estimated Post Reading Time ~

Working with Query Builder API

Search functionality is the backbone of almost all the enterprise web applications and AEM is no exception. AEM provides the QueryBuilder API to perform search operations in the JCR. Query Builder works in the following way 
  • Queries are converted into XPath by the Query Engine. There they are again converted into JCR SQL2.
  • JCR SQL2 query is executed by the Oak Engine.
  • Appropriate Oak Index will be picked up by the query. A query for which the index is not found becomes the traversal queries (traverses the whole repository) which should be avoided by creating an appropriate index.
  • Query Builder does not have its own index. It uses the Oak index.

Query Builder

A query builder accepts a query description (in the form of predicates), creates the query and searches the JCR based on the predicates passed. Without further ado, let's see the code. 
Here we are creating the Sling Servlet that will use the Query Builder to search all the assets under /content/dam matching to the search term passed.
  • Create a class named QueryBuilderServlet and paste the following code in it.
package org.redquark.demo.core.servlets;

import java.util.HashMap;
import java.util.Map;

import javax.jcr.Session;
import javax.servlet.Servlet;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.Hit;
import com.day.cq.search.result.SearchResult;

/**
 * @author Anirudh Sharma
 * 
 * This servlet uses the QueryBuilder API to fetch the results from the JCR
 */
@Component(service = Servlet.class, property = {
 Constants.SERVICE_DESCRIPTION + "=Query Builder servlet",
 "sling.servlet.methods=" + HttpConstants.METHOD_GET,
 "sling.servlet.paths=" + "/bin/demo/querybuilder"
})
public class QueryBuilderServlet extends SlingSafeMethodsServlet {

 /**
  * Generated serialVersionUID
  */
 private static final long serialVersionUID = 2610051404257637265 L;

 /**
  * Logger
  */
 private static final Logger log = LoggerFactory.getLogger(QueryBuilderServlet.class);

 /**
  * Injecting the QueryBuilder dependency
  */
 @Reference
 private QueryBuilder builder;

 /**
  * Session object
  */
 private Session session;

 /**
  * Overridden doGet() method which executes on HTTP GET request
  */
 @Override
 protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {

  try {

   log.info("----------< Executing Query Builder Servlet >----------");

   /**
    * This parameter is passed in the HTTP call
    */
   String param = request.getParameter("param");

   log.info("Search term is: {}", param);

   /**
    * Get resource resolver instance
    */
   ResourceResolver resourceResolver = request.getResourceResolver();

   /**
    * Adapting the resource resolver to the session object
    */
   session = resourceResolver.adaptTo(Session.class);

   /**
    * Map for the predicates
    */
   Map < String, String > predicate = new HashMap < > ();

   /**
    * Configuring the Map for the predicate
    */
   predicate.put("path", "/content/dam");
   predicate.put("type", "dam:Asset");
   predicate.put("group.p.or", "true");
   predicate.put("group.1_fulltext", param);
   predicate.put("group.1_fulltext.relPath", "jcr:content");

   /**
    * Creating the Query instance
    */
   Query query = builder.createQuery(PredicateGroup.create(predicate), session);

   query.setStart(0);
   query.setHitsPerPage(20);

   /**
    * Getting the search results
    */
   SearchResult searchResult = query.getResult();

   for (Hit hit: searchResult.getHits()) {

    String path = hit.getPath();

    response.getWriter().println(path);
   }
  } catch (Exception e) {

   log.error(e.getMessage(), e);
  } finally {

   if (session != null) {

    session.logout();
   }
  }
 }

}
  • Here, we are reading the query parameter param and based on this query parameter we will search the JCR in the path /content/dam
  • We are searching only the assets, which is defined by the property type=dam:Asset 
  • Now we are creating the Query object using the predicate map and the session object.
  • At last, we are getting the SearchResult from the query builder and then using the Hit object, we are getting the path of each result.
  • Deploy the code and executing the servlet by hitting the request - http://<host>:<port>/bin/demo/querybuilder?param=we.retail
  • You will get the following the result set on the browser window
1. /content/dam/we-retail-screens/we-retail-instore-logo.png
2. /content/dam/projects/we-retail/cover
3. /content/dam/we-retail-screens/italy.png
4. /content/dam/we-retail-screens/usa.png
5. /content/dam/we-retail/en/activities/running/marathon-shoes.jpg
6. /content/dam/we-retail/en/activities/running/running-woods-woman.jpg
7. /content/dam/we-retail/en/activities/running/running_4.jpg
8. /content/dam/we-retail/en/activities/running/fitness-woman.jpg
9. /content/dam/we-retail/en/activities/running/running_1.jpg
10. /content/dam/we-retail/en/activities/running/running_3.jpg
11. /content/dam/we-retail/en/activities/running/running_5.jpg
12. /content/dam/we-retail/en/activities/running/running_2.jpg
13. /content/dam/we-retail/en/activities/running/running-desert-woman.jpg
14. /content/dam/we-retail/en/activities/running/running-couple-mountain.jpg
15. /content/dam/we-retail/en/activities/snowboarding/man-snowboarder.jpg
16. /content/dam/we-retail/en/activities/snowboarding/extreme-championship-girls.jpg
17. /content/dam/we-retail/en/activities/snowboarding/freeride-downhill.jpg
18. /content/dam/we-retail/en/activities/hiking-camping/alpinists-rochefort-ridge.jpg
19. /content/dam/we-retail/en/activities/hiking-camping/hiker-anapurna.jpg
20. /content/dam/we-retail/en/activities/hiking-camping/trekker-ama-dablam.jpg


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.