Hi All,
I want to show search result count beside the each search facets which acts as filter on the search result returned by a free text search. For example I search "car" and my facets (filters) are Audi, Mercedes, BMW. So when end user clicks on these facets they only see pages which are tagged with that particular tag. I am able to fetch result by writing simple query builder query and logic is working perfectly fine.
Now I want to enhance my functionality and show number of search result beside each tag like Audi (10), Mercedes (23), BMW(18).
1. Simplest approach which comes to my mind is to fire separate query for each facet and get the search result count for them (i.e. 4 querys for this case and goes bad a number of search facet increases). This will add huge load on my server and would create performance issues.
2. Get all the result back and while processing them in JSP, I read all the pages and keep count of all the tags I encounter. Problem with this approach is as I am implementing pagination for search results (i.e I show only 10 results per page). Thus I have used predicates like p.offset and p.limit which will never give me whole search result, but rather only required 10 search result according to query parameter found in my search URL. I don't changing this to return all the results would be good solution as I have to start skipping result on the basis of pagination.
3. Third approach which I believe would be the best solution is to use Bucket API provided by CQ, which I assume would be able to get context of my search tags and thus automatically give me back counts without firing any extra query. But I am not able to totally understand how to use this com.day.cq.search.facets and com.day.cq.search.facets.buckets. I do see that OOTB search component does uses bucket API effectively and also get the required count for search result as required. It would be great if any one can tell me some pointers around this buckets API and how does the OOTB code works?
Thanks for your help in advance.
OOTB code http://localhost:4502/crx/de/index.jsp#/libs/foundation/components/search/search.jsp
<c:if test="${result.facets.tags.containsHit}">
<p><%=i18n.get("Tags")%></p>
<c:forEach var="bucket" items="${result.facets.tags.buckets}">
<c:set var="bucketValue" value="${bucket.value}"/>
<c:set var="tag" value="<%= tm.resolve((String) pageContext.getAttribute("bucketValue")) %>"/>
<c:if test="${tag != null}">
<c:set var="label" value="${tag.title}"/>
<c:choose>
<c:when test="<%= request.getParameter("tag") != null && java.util.Arrays.asList(request.getParameterValues("tag")).contains(pageContext.getAttribute("bucketValue")) %>">
${label} (${bucket.count}) - <a title="filter results" href="<c:url value="${currentPage.path}.html"><c:param name="q" value="${escapedQueryForHref}"/></c:url>">remove filter</a>
</c:when>
<c:otherwise>
<a title="filter results" href="
<c:url value="${currentPage.path}.html">
<c:param name="q" value="${escapedQueryForHref}"/>
<c:param name="tag" value="${bucket.value}"/>
</c:url>">
${label} (${bucket.count})
</a>
</c:otherwise>
</c:choose><br/>
</c:if>
</c:forEach>
</c:if>
Solved! Go to Solution.
Views
Replies
Total Likes
Hi All,
I have made is working and now I think I got some understanding how it can be done. Earlier for forming my Query Builder query I was creating a hashmap and then was using
query = queryBuilder.createQuery(PredicateGroup.create(PredicateParamMap), session); This somehow was not able to detect tags as facets. Now I have changed my code and using predicate group as below:-
SearchResult resultNew = null; // PredicateGroup group = new PredicateGroup(); // group.add(new Predicate("tags", "tagid").set("property", "jcr:content/cq:tags")); // tagPredicate.set("tagid", request.getParameter("tag")); //group.add(new Predicate("mytype", "type").set("type", "nt:file")); final QueryBuilder queryBuilder = getResourceResolver().adaptTo(QueryBuilder.class); final Session session = (Session) getResourceResolver().adaptTo(Session.class); PredicateGroup group = new PredicateGroup(); Predicate tagPredicate = new Predicate("tags", "tagid"); tagPredicate.set("property", "jcr:content/cq:tags"); tagPredicate.set("tagid", "properties:style"); group.add(tagPredicate); Query queryNew = queryBuilder.createQuery(group, session); resultNew = queryNew.getResult(); Map<String, Facet> facets = resultNew.getFacets(); for (String key : facets.keySet()) { System.out.println("Facet Key " + key); Facet facet = facets.get(key); System.out.println("Facet " + facet.toString()); if (facet.getContainsHit()) { for (Bucket bucket : facet.getBuckets()) { String value = bucket.getValue(); long count = bucket.getCount(); System.out.println("Value == "+ value + " count == "+ count); Map<String, String> params = bucket.getPredicate().getParameters(); System.out.println("\n Entering inside the search resuts \n"); for (String k : params.keySet()) { System.out.println("k == " + k); } } } }
Now I see tags getting detected as facets and buckets are getting generated for each associated tag
Views
Replies
Total Likes
I think you found the best way to implement the solution using option 3. Here are some info on facets and buckets
Facets are set of possible values found in current results, they provide options for more specific query
Facet are set of buckets, Buckets can be product, business, marketing in your case it is Audi, Mercedes and BMW
Buckets can be custom ranges too like
Facet = date range
Bucket = yesterday, last week, last year, last century and soon
You may find more information from the following link
docs.adobe.com/docs/en/cq/5-3/dam/customizing_and_extendingcq5dam/query_builder.html
As per the API here are the definitions of Facets and Buckets
Bucket | Bucket represents a single element of a search result categorization. |
Facet | Facet represents a single category that splits up a search result into multiple buckets . |
Views
Replies
Total Likes
Hi Shaji,
Thanks for the quick reply, I have already gone through the documents. I need some help in usage of API. :)
Views
Replies
Total Likes
Hi All,
I have made is working and now I think I got some understanding how it can be done. Earlier for forming my Query Builder query I was creating a hashmap and then was using
query = queryBuilder.createQuery(PredicateGroup.create(PredicateParamMap), session); This somehow was not able to detect tags as facets. Now I have changed my code and using predicate group as below:-
SearchResult resultNew = null; // PredicateGroup group = new PredicateGroup(); // group.add(new Predicate("tags", "tagid").set("property", "jcr:content/cq:tags")); // tagPredicate.set("tagid", request.getParameter("tag")); //group.add(new Predicate("mytype", "type").set("type", "nt:file")); final QueryBuilder queryBuilder = getResourceResolver().adaptTo(QueryBuilder.class); final Session session = (Session) getResourceResolver().adaptTo(Session.class); PredicateGroup group = new PredicateGroup(); Predicate tagPredicate = new Predicate("tags", "tagid"); tagPredicate.set("property", "jcr:content/cq:tags"); tagPredicate.set("tagid", "properties:style"); group.add(tagPredicate); Query queryNew = queryBuilder.createQuery(group, session); resultNew = queryNew.getResult(); Map<String, Facet> facets = resultNew.getFacets(); for (String key : facets.keySet()) { System.out.println("Facet Key " + key); Facet facet = facets.get(key); System.out.println("Facet " + facet.toString()); if (facet.getContainsHit()) { for (Bucket bucket : facet.getBuckets()) { String value = bucket.getValue(); long count = bucket.getCount(); System.out.println("Value == "+ value + " count == "+ count); Map<String, String> params = bucket.getPredicate().getParameters(); System.out.println("\n Entering inside the search resuts \n"); for (String k : params.keySet()) { System.out.println("k == " + k); } } } }
Now I see tags getting detected as facets and buckets are getting generated for each associated tag
Views
Replies
Total Likes
Views
Likes
Replies