Showing posts with label spell check in AEM. Show all posts
Showing posts with label spell check in AEM. Show all posts

Wednesday, 24 May 2017

AEM Search Suggestions

AEM provides out of the box Suggester API to populate suggestions for a particular keyword. com.day.cq.search.suggest.Suggester API provides methods to fetch suggestions and it provides a spell check feature as well.

An example would be:

import com.day.cq.search.suggest.Suggester;
import com.soh.services.SearchSuggestion;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;

/**
 * SOH Search Suggester
 */
@Component
@Service(SearchSuggestion.class)
public class SearchSuggestionImpl implements SearchSuggestion {
    /**
     * The Suggester Index
     */
    private static final String INDEX = "oak-cq:Page";

    /**
     * CQ Suggester Reference
     */
    @Reference
    private Suggester suggester;

    /**
     * 
     * @param keyword
     *            to search for
     * @return JSONArray containing search suggestions
     */
    @Override
    public JSONArray getSuggestions(String keyword, int noOfItems, ResourceResolver resourceResolver) {
        final boolean spellCheck = true;
        final JSONArray suggestions = new JSONArray();
        final Session session = resourceResolver.adaptTo(Session.class);
        int counter = 0;
        for (final String suggestion : suggester.getSuggestions(session, INDEX, keyword, spellCheck)) {
            counter++;
            suggestions.put(suggestion);
            if (counter == noOfItems) {
                break;
            }
        }
        if (suggestions.length() < 1) {
            final String spellSuggestion = suggester.spellCheck(session, keyword);
            for (final String suggestion : suggester.getSuggestions(session, INDEX, spellSuggestion, spellCheck)) {
                counter++;
                suggestions.put(suggestion);
                if (counter == noOfItems) {
                    break;
                }
            }
        }

        return suggestions;
    }
}

Further, we can configure our index to specify which JCR properties do we want to include while populating suggestions. useInSuggest="{Boolean}true" is the property that we have to specify. Here is a sample index which includes jcr:title property in the suggestions:


<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:oak="http://jackrabbit.apache.org/oak/ns/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:rep="internal"
    jcr:mixinTypes="[rep:AccessControllable]"
    jcr:primaryType="nt:unstructured">
    <customLuceneIndex
        jcr:primaryType="oak:QueryIndexDefinition"
        async="async"
        evaluatePathRestrictions="{Boolean}true"
        includedPaths="[/content/myproject]"
        reindex="{Boolean}false"
        type="lucene">
        <analyzers jcr:primaryType="nt:unstructured">
            <default
                jcr:primaryType="nt:unstructured"
                class="org.apache.lucene.analysis.standard.StandardAnalyzer">
                <stopwords/>
            </default>
        </analyzers>
        <indexRules jcr:primaryType="nt:unstructured">
            <cq:Page jcr:primaryType="nt:unstructured">
                <properties jcr:primaryType="nt:unstructured">
                    <jcrTitle
                        jcr:primaryType="nt:unstructured"
                        name="jcr:content/jcr:title"
                        nodeScopeIndex="{Boolean}true"
                        ordered="{Boolean}false"
                        propertyIndex="{Boolean}true"
                        type="String"
                        useInSuggest="{Boolean}true"/>
                </properties>
            </cq:Page>
        </indexRules>
    </customLuceneIndex>
</jcr:root>



Hope this helps!