SlingQuery

17

Click here to load reader

Transcript of SlingQuery

Page 1: SlingQuery

CIRCUITAN ADOBE DEVELOPER EVENTPRESENTED BY CITYTECH, INC.Use SlingQuery andwalk the tree with ease

Tomek Rękawek, Cognifide@TomaszRekawek

Page 2: SlingQuery

Sling APIResource parent = myResource.getParent(); for (Resource child : parent.getChildren()) { if (child.adaptTo(ValueMap.class).containsKey("myProperty")) { //... }}

efficient, especially for denormalized and well-structured content[1]easy to usebut:

a lot of while()s, iterators and nullcheckscode complexity is growing fast

[1] Efficient content structures and queries in CRX

Page 3: SlingQuery

Sling exampleFind the first ancestor with a given template.

String path = "/content/geometrixx/en/products/triangle/jcr:content/par";String homeTemplate = "/apps/geometrixx/templates/homepage";

Resource resource = resourceResolver.getResource(path);while ((resource = resource.getParent()) != null) { if (!resource.isResourceType("cq:Page")) { continue; } ValueMap map = resource.adaptTo(ValueMap.class); String cqTemplate = map.get("jcr:content/cq:template"); if (homeTemplate.equals(cqTemplate)) { break; }}resource.getPath();

Page 4: SlingQuery

SlingQuery exampleimport static com.cognifide.sling.query.api.SlingQuery.$;Resource resource = getResource("/content/geometrixx/en/products/triangle/jcr:content/par");

$(resource) .closest("cq:Page[jcr:content/cq:template=/apps/geometrixx/templates/homepage]")

$() is a valid method name in Java,it wraps resource(s) into an iterable SlingQuerycollectioneach method transforms the existing collectioninto a new one

API inspired by jQuery

Page 5: SlingQuery

Get all text componentsfrom the parsysr = getResource("/content/geometrixx/en/jcr:content/rightpar/teaser")

SlingQuery collection = $(r) .closest("cq:PageContent") .find("foundation/components/parsys#par") .children("foundation/components/text")

for (Resource c : collection) { println c.path}

each method returns new collectionSlingQuery object implements Iterable

Page 6: SlingQuery

Breadcrumbsr = getResource("/content/geometrixx/en/products/mandelbrot/overview/jcr:content/par")

Iterable<Page> breadcrumbs = $(r) .parents("cq:Page") .not("[jcr:content/hideInNav=true]") .map(Page.class)

for (Page p : breadcrumbs) { println p.title}

map() method creates a new Iterable<>adapting each resource to a given classresource.adaptTo(Page.class)approach compatible with Sling Models

Page 7: SlingQuery

Selector stringr = getResource("/content/geometrixx/en/products/mandelbrot")

$(r) .children("cq:PageContent") .children("foundation/components/parsys") .children("#title[jcr:title=Best in class][type=large]:first")

selector formatresource type or node type#resource-nameattributes in []modifiers, each prepended by :

all elements are optional

Page 8: SlingQuery

Advanced selectorsr = getResource("/content/geometrixx")

$(r) .find("[text*=square]:not(cq:PageContent):first") .closest("cq:Page") .find("#title, #image, #par:parent")

:not() accepts any valid selector:not(:not(:not(:first)))

:parent - only resources having childrenthere is a number of operators for square bracketsalternatives can be separated with a comma

Page 9: SlingQuery

Random imagernd = new java.util.Random()r = getResource("/content/dam/geometrixx/travel")

$(r) .children("dam:Asset") .filter({ rnd.nextFloat() > 0.9 } as Predicate) .first()

in Java it'd look like this:// ... .filter(new Predicate<Resource>() { @Override public boolean accepts(Resource resource) { return rnd.nextFloat() > 0.9; } });

Page 10: SlingQuery

Siblings but not mer = getResource("/content/geometrixx/en/products/mandelbrot/jcr:content/par/image")

myPage = $(r).closest("cq:Page")

result = myPage .siblings("cq:Page") .not(myPage)

the SlingQuery collection is immutableeach method returns a new collection

any Iterable<Resource> may be used as a filter

Page 11: SlingQuery

Find all pages withgiven template$(resourceResolver) .find("cq:PageContent[cq:template=/apps/geometrixx/templates/homepage]") .parent()

$(resourceResolver) creates a collectioncontaining /find() iterates over the whole subtree

Page 12: SlingQuery

Search strategyr = getResource("/content/geometrixx/en")

result = $(r) .searchStrategy(DFS) .find("cq:Page")

for (Resource c : result) { println c.path}

strategies: DFS, BFS, QUERYQUERY tries to rewrite find() selector into JCR-SQL2

the result is filtered once more

Page 13: SlingQuery

Find method vs JCRfind() is powerful but may be dangerousit should be used only for small subtreesif you want to query a large space, use JCR-SQL[2]or XPathif your SlingQuery processes more than 100resources, you'll get a warning in the logs:

28.05.2014 13:35:49.942 *WARN* [0:0:0:0:0:0:0:1 [1401276949857] POST /bin/groovyconsole/post.json HTTP/1.1] SlingQuery Number of processed resources exceeded 100. Consider using a JCR query instead of SlingQuery. More info here: http://git.io/h2HeUQ

Page 14: SlingQuery

Lazinessresult = $(resourceResolver) .searchStrategy(DFS) .find() .slice(10, 20)

result.toString()

we don't query resources unless we need theminvoking the SlingQuery method adds a newfunction to the chainfunctions are executed by the final iterator (likethe one created by the for() loop)all functions are lazy

expect the last() function

Page 15: SlingQuery

Resourcescode & docs

global Maven repository

https://github.com/Cognifide/Sling-Query

<dependency> <groupId>com.cognifide.cq</groupId> <artifactId>sling-query</artifactId> <version>1.4.4</version></dependency>

Page 16: SlingQuery

Questions?

Page 17: SlingQuery

Thank you!