Optimized Query Builder query for getting search result count for each facet.
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>