Wildcard Case Insensitive Search using AEM Query Builder API

I have been struggling with a wildcard case insensitive search in query builder API so I thought of sharing its solution as searching for content in Adobe Experience Manager (AEM) can sometimes be challenging, especially when you need to perform case-insensitive searches with wildcard support. In this blog post, we’ll explore how to achieve this using the AEM Query Builder API with a custom predicate evaluator.
Introduction
Imagine you have a node structure in AEM like /content/mydata/stores
, where each store node contains properties such as storeName
. You want to search for stores by their names in a case-insensitive manner, allowing for partial matches. This is where a custom predicate evaluator comes in handy.
The Challenge
The default Query Builder API in AEM does not support case-insensitive searches with wildcards out of the box. To overcome this limitation, we need to create a custom predicate evaluator that extends the functionality of the Query Builder API.
Solution: Custom Predicate Evaluator
We’ll create a custom predicate evaluator named CaseInsensitiveLike
that allows us to perform case-insensitive searches using the jcr:like
function with the fn:lower-case
function in XPath.
Step-by-Step Implementation
- Create the Custom Predicate Evaluator: First, we need to create a Java class that extends
AbstractPredicateEvaluator
and overrides thegetXPathExpression
method. This class will be annotated with@Component
to register it as an OSGi component.
@Component(factory = "com.day.cq.search.eval.PredicateEvaluator/likeIgnoreCase")
public class CaseInsensitiveLike extends AbstractPredicateEvaluator {
private static final Logger log = LoggerFactory.getLogger(CaseInsensitiveLike.class);
static final String PREDICATE_PROPERTY = "property";
@Override
public String getXPathExpression(Predicate predicate, EvaluationContext context) {
String property = predicate.get(PREDICATE_PROPERTY);
String value = predicate.get("value").toLowerCase();
return "jcr:like(fn:lower-case(@" + property + "), '" + value + "')";
}
}
2. Register the Custom Predicate Evaluator: Ensure that the custom predicate evaluator is registered correctly in the OSGi container. This is done using the @Component
annotation with the appropriate factory name.
3. Use the Custom Predicate in Your Search Query: Now that we have our custom predicate evaluator, we can use it in our search queries. Here’s an example of how to use it in a query map:
Map<String, String> queryMap = new HashMap<>();
queryMap.put("path", "content/mydata/stores");
queryMap.put("type", "nt:unstructured");
queryMap.put("likeIgnoreCase.property", "storeName");
queryMap.put("likeIgnoreCase.value", "%" + storeName.trim() + "%");
In this example, storeName
is the search term provided by the user. The likeIgnoreCase.property
and likeIgnoreCase.value
parameters are used to specify the property to search and the value to match, respectively.
Conclusion
By creating a custom predicate evaluator, we can extend the AEM Query Builder API to support case-insensitive searches with wildcards. This approach provides a flexible and powerful way to search for content in AEM, making it easier to find the information you need. Feel free to customize the code and adapt it to your specific use case.