Search code examples
aemquery-builderjcr-sql2

Querybuilder search for only single tag


I am using Querybuilder to search for pages that are tagged with specific tags. The issue is Querybuilder is creating an xpath query that searches for all child tags of the tag along-with the main tag. I want it to search for only the parent tag and not the child tags. Using PredicateGroup to combine all tags--

map.put("path", searchPath);
map.put("type", "cq:Page");
map.put("orderby", "@jcr:content/cq:lastModified");
PredicateGroup tagsPredicateGroup = new PredicateGroup();
PredicateGroup searchGroup = PredicateGroup.create(map);
PredicateGroup tagsPredicateGroup = new PredicateGroup();
        tagsPredicateGroup.setAllRequired(false);
        if (tagsArray != null && tagsArray.length > 0) {
            for (Tag tag : tagsArray) {
                tagsPredicateGroup.add(createSingleTagPredicate(tag));
            }
        }
searchGroup.add(tagsPredicateGroup);
Query query = queryBuilder.createQuery(searchGroup, session);
query.setHitsPerPage(10);
query.setStart(0);

private PredicateGroup createSingleTagPredicate(Tag tag) {
        Map<String, String> tagMap = new HashMap<String, String>();
        tagMap.put("tagid.property", "jcr:content/cq:tags");
        tagMap.put("tagid", tag.getTagID());
        return PredicateGroup.create(tagMap);
    }

If a component is configured to search for geometrixx-outdoors:apparel and geometrixx-media:events tags; then it also returns those pages which are tagged with geometrixx-outdoors:apparel/coats and geometrixx-media:events/festivals as well. How can I make it search for only the parent tag and not the child tag using querybuilder?


Solution

  • The tags predicate is designed to take child tags and it's second form (path based) into account. If you don't want this and you want an exact match, you need to query it like a regular property. You're querymap should look similar to this.

    map.put("path","/content/geometrixx-outdoors");
    map.put("type","cq:Page");
    map.put("property","jcr:content/cq:tags");
    map.put("property.value","geometrixx-outdoors:apparel");
    

    If you need to query for multiple tag id's which should be OR'd => ("A" or "B" or "C")

    map.put("path","/content/geometrixx-outdoors");
    map.put("type","cq:Page");
    map.put("property","jcr:content/cq:tags");
    map.put("property.1_value","geometrixx-outdoors:apparel");
    map.put("property.2_value","geometrixx-media:events");
    map.put("property.3_value","mynamespace:my-tag");
    

    If you need to query for multiple tag id's which should be AND'd => ("A" and "B" and "C")

    map.put("path","/content/geometrixx-outdoors");
    map.put("type","cq:Page");
    map.put("property","jcr:content/cq:tags");
    map.put("property.and","true");
    map.put("property.1_value","geometrixx-outdoors:apparel");
    map.put("property.2_value","geometrixx-media:events");
    map.put("property.3_value","mynamespace:my-tag");
    

    Important note, I've only shown the querying on id only. If you don't want to miss any potential results, you should also add the path of the tag in question to the query so that you query on both "tag id" and "tag path" within the field in question since tag path is a valid value for a 'tag'.