January 6, 2026
AEM Query Builder and JCR-SQL2
In Adobe Experience Manager (AEM), all content is stored in a JCR (Java Content Repository). To fetch, search, or manipulate this content…

By Yeti Venkatrao
4 min read
In Adobe Experience Manager (AEM), all content is stored in a JCR (Java Content Repository). To fetch, search, or manipulate this content, AEM provides multiple ways to query the repository.
The three most common ways to query content in AEM are:
- Query Builder API
- JCR-SQL2
- XPath
- Query Builder API:
The AEM Query Builder API is a high-level, predicate-based API used to search and retrieve content from the JCR (Java Content Repository).
It abstracts low-level query languages like JCR-SQL2 and XPath queries, allowing developers to create efficient, secure, and readable queries using simple key-value predicates.
pathtypepropertydaterange
Query Builder automatically leverages Oak Indexes, which helps improve query performance.
Query Builder Console :
AEM provides a built-in console to test and debug Query Builder queries:
http://localhost:4502/libs/cq/search/content/querydebug.htmlhttp://localhost:4502/libs/cq/search/content/querydebug.html
Commonly Used Query Builder Filters (Predicates):
1) Type Filter: The Type filter is used to specify the node type to search for, such as pages, assets, or components. This query returns all nodes of type cq:Page.
type:cq:Pagetype:cq:Page2) Path Filter: The Path filter restricts the search to a specific location in the JCR repository. It improves performance by avoiding unnecessary traversal of the entire repository. This query searches only under the /content/we-retails/us path.
path=/content/we-retail/uspath=/content/we-retail/us3) Property Filter: The Property filter is used to search for nodes based on specific property names and values.
property=jcr:title
property.value=Menproperty=jcr:title
property.value=MenEx:
type=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.value=Mentype=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.value=Men
It supports the following operations:
- equals (default)
- not (To exclude nodes with specific property values)
property=jcr:title
property.operation=not
property.value=Homepageproperty=jcr:title
property.operation=not
property.value=HomepageEx:
type=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=not
property.value=Mentype=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=not
property.value=Men- like (To match partial values (e.g., using % wildcards))
property=jcr:title
property.operation=like
property.value=%Home%property=jcr:title
property.operation=like
property.value=%Home%Ex:
type=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=like
property.value=%Men%type=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=like
property.value=%Men%
- exists (To find nodes where a specific property exists)
property=jcr:title
property.operation=existsproperty=jcr:title
property.operation=existsNote: we are just checking if the property exists on the Node, not what its value is.
Ex:
type=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=existstype=cq:PageContent
path=/content/we-retail/us
property=jcr:title
property.operation=exists4) Date Filter: The Date Filter is used to search content based on date-related properties, such as when content was created, last modified, or last replicated.
Some common date properties are included in our JCR:
jcr:created— Date when the content was created.cq:lastModified— Date when the content was last modified.cq:lastReplicated— Date when the content was last replicated.
Structure of the Date Filter:
daterange.property=<property-name>
daterange.lowerBound=<start-date>
daterange.upperBound=<end-date>daterange.property=<property-name>
daterange.lowerBound=<start-date>
daterange.upperBound=<end-date>Date Filter Properties:
daterange.property→ The property you want to filter on (e.g.,cq:lastModified)daterange.lowerBound→ The starting date of your rangedaterange.upperBound→ The ending date of your rangdaterange.includeLower=true|false→ Include/exclude the lower bound date (default: true)daterange.includeUpper=true|false→ Include/exclude the upper bound date (default: true)
Date Format:
- Query Builder expects dates in the ISO format:
yyyy-MM-ddoryyyy-MM-dd'T'HH:mm:ss.SSSXXX
Practical Examples:
Ex1: Get pages modified in 2024:
- Returns all pages under
/content/we-retail/usmodified in 2024.
type=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.upperBound=2024-12-31type=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.upperBound=2024-12-31Ex2: Include only pages modified after Jan 1, 2024
- Returns all pages modified on or after 1st Jan 2024.
- No upper limit, so all future modifications are included.
type=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.includeLower=truetype=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.includeLower=trueEx3: Exclude the end date:
- Returns pages modified before 31st Dec 2024, but does not include pages modified exactly on 31st Dec.
type=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.upperBound=2024-12-31
daterange.includeUpper=falsetype=cq:PageContent
path=/content/we-retail/us
daterange.property=cq:lastModified
daterange.lowerBound=2024-01-01
daterange.upperBound=2024-12-31
daterange.includeUpper=false- JCR-SQL2:
JCR-SQL2 is a query language for querying the JCR (Java Content Repository) in AEM. It is an extension of SQL that is tailored to work with the content repository model. It lets you interact with content in AEM using SQL-like syntax.
How to Execute JCR-SQL2:
- Open CRX/DE Lite
- Click on Tools → Query
- Select Query Type →
SQL2 - Write your JCR-SQL2 query
- Click Execute
Basic Syntax
The basic structure of a JCR-SQL2 query looks like this:
SELECT <columns> FROM <node-type> WHERE <condition>SELECT <columns> FROM <node-type> WHERE <condition>SELECT: Specifies the properties or nodes you want to retrieve.FROM: Defines which node types to query.WHERE: Adds filters or conditions.
Example 1: Simple Query
To get all nodes of type cq:Page:
SELECT * FROM [cq:Page]SELECT * FROM [cq:Page]- This query retrieves all the properties of nodes that are of type
cq:Page.
Ex 2: Querying Specific Properties
To get only the jcr:title and jcr:created properties of cq:Page nodes:
SELECT [jcr:title], [jcr:created] FROM [cq:Page]SELECT [jcr:title], [jcr:created] FROM [cq:Page]3.XPath:
XPath (XML Path Language) is one of the older query languages used to search content in JCR (Java Content Repository).
In AEM, XPath was widely used before JCR-SQL2 and Query Builder, but today it is considered a legacy approach.
XPath is a path-based query language that allows you to navigate through the JCR node hierarchy using expressions similar to file paths.
XPath queries work by traversing nodes and applying conditions on properties.
Basic XPath Syntax in AEM:
/jcr:root/<path>//element(<node-name>, <node-type>)/jcr:root/<path>//element(<node-name>, <node-type>)Execute XPath Queries:
- Open CRX/DE Lite
- Go to Tools → Query
- Select Query Type → XPath
- Enter your XPath query
- Click Execute
Ex 1: Get all pages under a path
- This returns all nodes of type
cq:Pageunder/content/we-retail/us.
/jcr:root/content/we-retail/us//element(*, cq:Page)/jcr:root/content/we-retail/us//element(*, cq:Page)Ex 2: Filter by property value
- Returns pages where
jcr:titleis exactly Men.
/jcr:root/content/we-retail/us//element(*, cq:Page)
[@jcr:title='Men']/jcr:root/content/we-retail/us//element(*, cq:Page)
[@jcr:title='Men']Ex3: Partial match using contains()
- Returns pages whose title contains the word "Men".
/jcr:root/content/we-retail/us//element(*, cq:Page)
[contains(@jcr:title, 'Men')]/jcr:root/content/we-retail/us//element(*, cq:Page)
[contains(@jcr:title, 'Men')]Thank you for reading! Stay tuned for more AEM-related blogs and tutorials.