Query Module

The XWiki Query module allows querying the XWiki Model using a variety of query languages. The 2 supported Query languages are:

  • XWiki Query Language (XWQL) for which the grammar is defined on GitHub. The XWQL implementation translates queries into HQL which are then executed using Hibernate against the RDBMS. Any JPQL query is a correct XWQL query which means that the majority of HQL queries will work with XWQL when executed on the XWiki Hibernate store.
  • Hibernate Query Language (HQL) which is a JQPL superset.

Differences Between XWQL and HQL

XWQLwhere upper(doc.name) like 'WEBHOME'The LIKE statement cannot be transformed in XWQL
HQLwhere upper(doc.name) like upper('webhome')

As explained here, the syntax for the use of the comparison operator [ NOT ] LIKE in a conditional expression is string_expression [NOT] LIKE pattern_value [ESCAPE escape_character]  where:

  • the string_expression must have a string value
  • the pattern_value is a string literal or a string-valued input parameter in which an underscore (_) stands for any single character, a percent (%) character stands for any sequence of characters (including the empty sequence), and all other characters stand for themselves
  • the optional escape_character is a single-character string literal or a character-valued input parameter and is used to escape the special meaning of the underscore and percent characters in pattern_value.

Also, when using XWQL, it is mandatory to use aliases when filtering for multiple properties of an object. When querying on multiple objects, the clause doc.object(classname1) OR doc.object(classname2) won't work because XWQL expects to find both objects attached to the page when in reality, you either have both objects or only one of them. The solution here is a HQL nested query.

Finally, it is not possible to use the abbreviated syntax doc.object(classname).propertyName multiple times on the same object property in the same query. The solution is again a HQL query.

XWiki-Specific Extensions in XWQL over JPQL

  • Short form queries:
    • where <expr> means select doc.fullName where <expr>
    • from <fromlist> [where <expr>] means select doc.fullName from Document as doc, <fromlist> [where <expr>]
  • Special syntax for XWiki objects in from and where clauses:
    • from doc.object(Class) as obj
    • where doc.object(Class).prop = 'something'

Query Filters

Query filters allow filtering query results. The available filters are:

  • the hidden filter allows excluding hidden documents.
  • the unique filter makes sure unique results are retrieved by a query and it only works on queries selecting full names of XWiki documents.
  • the count filter transforms queries in order to make them return the total number of results instead of a list of results.
  • the language filter add an internal SELECT clause in order to return the document language. The result is a List<Object[]> where:
    • Object[0] is the document name 
    • Object[1] is the document language (en, fr, fr_FR)
  • the currentLanguage filter return only documents in the current language.

To learn how to use filters, check the below examples.

The Query Manager

This API is now deprecate so you should instead use:

  • $services.query.xwql("xwqlstatement").execute()
  • $services.query.hql("hqlstatement").execute()

in Velocity and

  • services.get("query").xwql(xwqlstatement).execute()
  • services.get("query").hql(hqlstatement).execute()

in Groovy

The principle is to get a reference to the Query Manager, then call a method on it to create a query for the given query language. 

HQL$xwiki.queryManager.createQuery(hqlstatement, "hql").execute()

From Java Components

Get a QueryManager injected:

     * Secure query manager that performs checks on rights depending on the query being executed.

   private QueryManager queryManager;

Obtain and execute a query:

this.queryManager.createQuery(statement, Query.XWQL).execute();


All queries starting with select require programming rights to execute.
Query DescriptionXWQLHQL
Query listing all documents<empty query><empty query>
Query listing all documents created after a given datewhere doc.creationDate > '2008-01-01'where doc.creationDate > '2008-01-01'
Query listing all documents last updated by a given userwhere doc.author = 'XWiki.LudovicDubost'where doc.author = 'XWiki.LudovicDubost'
Query listing all documents containing XWiki Objects (XObject) of a given XWiki Class (XClass)from doc.object(XWiki.XWikiUsers) as user, BaseObject as obj where doc.fullName = obj.name and obj.className = 'XWiki.XWikiUsers'
Query on XObjects and filtering on XObject property valuewhere doc.author = 'XWiki.LudovicDubost' and doc.object(XWiki.XWikiUsers)
.email like '%xwiki.com'
, BaseObject as obj, StringProperty as prop where doc.fullName = obj.name and obj.className = 'XWiki.XWikiUsers' and obj.id=prop.id.id and prop.id.name='email' and prop.value like '%xwiki.com' and doc.author ='XWiki.LudovicDubost'
Query on 2 XObjectswhere doc.object(XWiki.XWikiUsers)
.email like '%xwiki.com'  and  doc.object(XWiki.ArticleClass)
.content like '%ludovic%'
, BaseObject as obj, StringProperty as prop, BaseObject as obj2, LargeStringProperty as contentprop where doc.fullName = obj.name and obj.className = 'XWiki.XWikiUsers' and obj.id=prop.id.id and prop.id.name='email' and prop.value like '%xwiki.com' and doc.fullName=obj2.name and obj2.className='XWiki.ArticleClass' and obj2.id=contentprop.id.id and contentprop.id.name='content' and contentprop.value like '%ludovic%'
Search blogs per categorywhere doc.fullName <> 'XWiki.ArticleClassTemplate'
and :category member of doc.object(XWiki.ArticleClass)
, BaseObject as obj, DBStringListProperty as prop join prop.list list where obj.name=doc.fullName and obj.className='XWiki.ArticleClass' and obj.name<>'XWiki.ArticleClassTemplate' and obj.id=prop.id.id and prop.id.name='category'  and list='${category}' order by doc.creationDate desc
List all tagsselect distinct obj.tags from Document doc, doc.object(XWiki.TagClass) as objselect distinct tag from BaseObject as obj, DBStringListProperty as prop join prop.list as tag where obj.className='XWiki.TagClass' and obj.id=prop.id.id and prop.id.name='tags'

Velocity XWQL Examples

1. Return all the results matching the XWQL statement: $services.query.xwql("xwqlstatement").execute()

2. Limit the number of returned results: $services.query.xwql("xwqlstatement").setLimit(5).execute()

3. Set an offset: $services.query.xwql("xwqlstatement").setOffset(5).execute()

4. Set the wiki on which to run the query This query requires Programming Rights


5. Add filters: 

  • hidden: $services.query.xwql("xwqlstatement").addFilter("hidden").execute()
  • unique: $services.query.xwql("xwqlstatement").addFilter("unique").execute()
  • count: $services.query.xwql("xwqlstatement").addFilter("count").execute() OR $services.query.xwql("xwqlstatement").count()
  • language: $services.query.xwql("xwqlstatement").addFilter("language").execute()
  • currentLanguage: $services.query.xwql("xwqlstatement").addFilter("currentlanguage").execute()


Bind a String 

Return all XWiki documents having a comment that contains the String "test":

#set($query = $services.query.xwql("SELECT doc.fullName FROM Document doc, doc.object(XWiki.XWikiComments) com 
WHERE doc.translation = 0 AND com.comment LIKE :value"))
value", "%test%").execute()

Bind a Boolean

Return all XWiki active users: 

#set($query = $services.query.xwql("select doc.fullName from Document doc, doc.object(XWiki.XWikiUsers) u WHERE u.active = :var"))
$query.bindValue("var", 1)).execute()

Bind an Array or a List

#set ($query = $services.query.xwql('WHERE doc.name IN (:myList)'))
$query.bindValue('myList', ['Activity', 'BlogPostClass', 'Welcome']).execute()

Velocity HQL Examples

The 2 below examples illustrate the the use cases presented in the previous section.

1. List the XWiki users for which the first name begins with the letter "A" or with the letter "M".

$services.query.hql("SELECT doc.fullName FROM XWikiDocument AS doc, BaseObject AS obj, StringProperty AS prop WHERE
doc.fullName = obj.name AND obj.className = 'XWiki.XWikiUsers' AND obj.id=prop.id.id AND prop.id.name='first_name'
AND (prop.value LIKE 'A%' OR prop.value LIKE 'M%')").execute()

2. Display the XWiki users for which the first name begins with the letter "A" or have an "Tag.TagClass" containing the tag "test".

$services.query.hql("SELECT doc.fullName FROM XWikiDocument AS doc WHERE doc.fullName IN
(SELECT doc1.fullName FROM XWikiDocument AS doc1, BaseObject AS obj1, StringProperty AS prop
WHERE doc1.fullName = obj1.name AND obj1.className = 'XWiki.XWikiUsers' AND obj1.id=prop.id.id
AND prop.id.name='first_name' AND prop.value LIKE 'R%') OR doc.fullName IN
(SELECT doc2.fullName FROM XWikiDocument AS doc2, BaseObject AS obj2, LargeStringProperty AS prop2 WHERE
doc2.fullName = obj2.name AND obj2.className='Tag.TagClass' AND obj2.id=prop2.id.id AND prop2.id.name = 'privateTags'
AND prop2.value LIKE '%test%')").execute()


Related Pages

Trying to decide between Cloud and On Premise? See the comparison on the XWiki Help Center.

Search this space