AEM 6510 - Assets Admin Search Rail Predicate to search based on Partial Filename, Case Ignored

Goal


AEM Assets Omnisearch does a full text search and is not nodename (or filename) based. XPath query generated by Omnisearch is something like below...

              (/jcr:root/content/dam//element(*, nt:folder)[(jcr:contains(., 'show'))] | /jcr:root/content/dam//element(*, dam:Asset)[(jcr:contains(., 'show'))])

Solution discussed below performs a search based on filename (and not file content) running the following query in AEM...

              (/jcr:root/content/dam//element(*, nt:folder)[(jcr:like(fn:lower-case(fn:name()), '%show%') and jcr:contains(., 'png'))] | /jcr:root/content/dam//element(*, dam:Asset)[(jcr:like(fn:lower-case(fn:name()), '%show%') and jcr:contains(., 'png'))])

For Assets search form Metadata Exists predicate check this post


Search Filter in Rail



Assets Search form Configuration




Solution


1) Login to CRXDe Lite and add the File name predicate configuration eaemignorecasenodename  in /apps/settings/dam/search/facets/formbuilderconfig/predicatetypes/items

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root 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"
    jcr:primaryType="cq:Page">
    <adminui/>
    <search jcr:primaryType="nt:unstructured">
        <facets jcr:primaryType="nt:unstructured">
            <formbuilderconfig jcr:primaryType="nt:unstructured">
                <predicatetypes jcr:primaryType="nt:unstructured">
                    <items jcr:primaryType="nt:unstructured">
                        <eaemignorecasenodename
                            jcr:primaryType="nt:unstructured"
                            fieldLabel="Filename"
                            fieldPropResourceType="/apps/eaem-search-form-nodename-predicate/nodename-field"
                            fieldResourceType="/apps/eaem-search-form-nodename-predicate/nodename-predicate"
                            fieldTitle="Experience AEM Filename Predicate"
                            fieldViewResourceType="granite/ui/components/foundation/form/textfield"
                            renderType="text"/>
                    </items>
                </predicatetypes>
            </formbuilderconfig>
        </facets>
    </search>
</jcr:root>

2) Create the configuration page for predicate (fieldPropResourceType in step 1) /apps/eaem-search-form-nodename-predicate/nodename-field/nodename-field.jsp with the following code

<%@include file="/libs/granite/ui/global.jsp" %>
<%@ page session="false" contentType="text/html" pageEncoding="utf-8"
         import="com.adobe.granite.ui.components.Config" %>

<%
    String key = resource.getName();
    String metaType = "eaemignorecasenodename";

    String fieldLabel = i18n.get("Filename");
%>

<input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key) %>">
<input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/jcr:primaryType") %>" value="nt:unstructured">
<input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/sling:resourceType") %>" value="/apps/eaem-search-form-nodename-predicate/nodename-predicate">
<input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/fieldLabel") %>" value="<%= fieldLabel %>">
<input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/metaType") %>" value="<%= metaType %>">

<div><h3><%= i18n.get("Filename predicate")%></h3></div>

<% request.setAttribute ("com.adobe.cq.datasource.fieldtextplaceholder", i18n.get("Filename"));%>

<sling:include resource="<%= resource %>" resourceType="dam/gui/coral/components/admin/customsearch/formbuilder/predicatefieldproperties/fieldlabelpropertyfield"/>

<sling:include resource="<%= resource %>" resourceType="granite/ui/components/foundation/form/formbuilder/formfieldproperties/titlefields"/>

<sling:include resource="<%= resource %>" resourceType="granite/ui/components/foundation/form/formbuilder/formfieldproperties/deletefields"/>


3) Create the predicate widget render html (fieldResourceType in step 1) /apps/eaem-search-form-nodename-predicate/nodename-predicate/nodename-predicate.jsp with following code

<%@include file="/libs/granite/ui/global.jsp" %>
<%@ page session="false" contentType="text/html" pageEncoding="utf-8"
           import="com.adobe.granite.ui.components.Config"%>
<%@ page import="com.adobe.granite.ui.components.AttrBuilder" %>

<%
    Config cfg = new Config(resource);
    String name = cfg.get("text", i18n.get("Property"));
    String metaType = cfg.get("metaType", "eaemignorecasenodename");

    boolean foldableOpen = cfg.get("open", true);
    String selected = foldableOpen ? "selected":"";

    AttrBuilder inputAttrs = new AttrBuilder(request, xssAPI);
    inputAttrs.add("type", "text");
    inputAttrs.add("name", metaType);
    inputAttrs.addClass("coral-Form-field coral-Textfield coral-DecoratedTextfield-input");
    inputAttrs.add("placeholder", "Partial or full name, any case...");
%>
<coral-accordion variant="large">
    <coral-accordion-item "<%=selected%>" data-metaType="checkboxgroup" data-type="eaemignorecasenodename">
        <coral-accordion-item-label><%= xssAPI.encodeForHTML(name) %></coral-accordion-item-label>
        <coral-accordion-item-content class="coral-Form coral-Form--vertical">
            <input <%=inputAttrs.build()%>>
        </coral-accordion-item-content>
    </coral-accordion-item>
</coral-accordion>

4) Add the predicate evaluator apps.experienceaem.assets.IgnoreCaseNodeNamePredicateEvaluator for searching using partial file name, case ignored...

package apps.experienceaem.assets;

import com.day.cq.search.Predicate;
import com.day.cq.search.eval.AbstractPredicateEvaluator;
import com.day.cq.search.eval.EvaluationContext;
import com.day.cq.search.eval.JcrPropertyPredicateEvaluator;
import org.apache.commons.lang3.StringUtils;
import org.osgi.service.component.annotations.Component;

@Component(
        factory = "com.day.cq.search.eval.PredicateEvaluator/eaemignorecasenodename"
)
public class IgnoreCaseNodeNamePredicateEvaluator extends AbstractPredicateEvaluator {
    public String getXPathExpression(Predicate predicate, EvaluationContext context) {
        String value = predicate.get(predicate.getName());

        if(StringUtils.isEmpty(value)){
            return null;
        }

        return "jcr:like(fn:lower-case(fn:name()), '%" + value.toLowerCase() + "%')";
    }
}


No comments:

Post a Comment