HomeBackend Development › Querying content (QueryBuilder & JCR-SQL2)

Querying content (QueryBuilder & JCR-SQL2)

Purpose: Find content efficiently: choosing the API, writing index-backed queries, and avoiding traversal warnings.

Who this page is for

AudienceWhy it matters to you
Backend engineersSearch and listing features
All engineersDebugging content questions

First question: do you even need a query?

If you know the path shape (/content/phi/plans/*), iterate children — it is faster and index-free. Query when matching by property values across unknown locations.

The APIs

APIStyleUse
QueryBuilderMap of predicates, AEM-specificApp code — readable, supports facets, pagination
JCR-SQL2SQL-ish standardTooling, complex conditions, ad hoc analysis
XPathLegacyRead-only knowledge — you'll meet it in old code

QueryBuilder example — gold-tier plan pages

type=cq:Page
path=/content/phi/plans
1_property=jcr:content/isGoldTier
1_property.value=true
orderby=@jcr:content/jcr:title
p.limit=20

(Test interactively at /libs/cq/search/content/querydebug.html.)

Indexes or it didn't happen

Every production query must be backed by an Oak index; unindexed queries fall back to traversal (walking nodes) and log Traversal query warnings before eventually being blocked at a node-count limit.

RuleWhy
Check the plan with "Explain Query" (Operations → Diagnosis)Confirms which index serves it
Add custom property indexes for your query patterns/oak:index definitions, shipped as code
Constrain path + type in every querySmaller index cost, better plans
Paginate (p.limit / offset or keyset patterns)Never load unbounded result sets

Common mistakes

Quick navigation