CQL Syntax and Solr Translation
Reference
Introduction
The Confluence Query Language is used in Confluence to build complex document queries. The Query module supports some of it and translate it to Solr. Here is some documentation on what is (not) supported and how.
Humility notice
While a comprehensive, updated documentation is always better, it may be incomplete or get outdated. As user-unfriendly as it is, you can try to have a look at the automated tests of the CQL Query module to get more details (please improve the documentation if you do so, if you can).
Upstream reference
Atlassian documents CQL here: https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/
We try to follow upstream. Divergeances will be considered bugs. Most of what is documented at this link should work as is. If the documentation you are currently is lacking, you can try stuff documented there and expect it to work.
However, due to the fact XWiki and Confluence don't work the same way and don't have the exact same feature set (and sometime they have equivalent features that don't work the same way), there will always be differences and unsupported stuff.
Unsupported features
Whenever a field we are aware of but we don't support yet is encountered, the query translator should throw an exception saying something like "Field [space.title] is not supported yet (line 1, col 1, pos 0)]":

Similarly, when a type is unsupported, a message like "CQL type [comment] is not supported yet (line 1, col 8, pos 7)" will be thrown.
Unknown fields will cause a message like "Field [unknown] is unknown".
Known unsupported types, fields and functions
- Fields favourite, favorite, macro, mention, watcher, space.title
- Functions favouriteSpaces, recentlyViewedContent, recentlyViewedSpaces
- Types attachment, comment
Supported features
- Fields: see how fields are translated
- Functions: currentUser, currentSpace, now, startOfDay, endOfDay, startOfWeek, endOfWeek, startOfMonth, endOfMonth, startOfYear, endOfYear, currentContent (with fields id, content, parent and ancestor)
- Types page, blogpost
Reserved words
Reserved words are as documented in the official CQL documentation, and can't be used as field names: after, and, as, avg, before, begin, by, commit, contains, count, distinct, else, empty, end, explain, from, having, if, in, inner, insert, into, is, isnull, left, like, limit, max, min, not, null, or, order, outer, right, select, sum, then, was, where, update.
How fields are translated
| CQL | Solr | Known limitations |
|---|---|---|
| creator, contributor, user, user.fullname,user.accountid | creator | these fields only work with the currentUser() function |
| created | creationdate | |
| lastmodified | date | |
| type | type and class | For page, complex expressions are generated so page doesn't match blogpost. type = blogpost is translated to class:Blog.BlogPostClass. Comments and attachments are not supported. |
| label | property.XWiki.TagClass.tags | |
| space | space_facet | |
| space.key | space_facet | |
| text | title, property.XWiki.TagClass.tags and content | these fields are combined with an OR. While it is possible to match content exactly in Confluence, it's not possible in XWiki and the expression will match any document with content *containing* the value |
| title | title_sort | title_sort is used because Confluence matches exactly |
How operators are translated
- field = v is converted to solrfield:v
- field != v is converted to -solrfield:v
- field > v is converted to solrfield:{v TO *]
- field >= v is converted to solrfield:{v TO *]
- field < v is converted to solrfield:[* TO v}
- field <= v is converted to solrfield:[* TO v]
- field v is converted to solrfield:v
- field ! v is converted to -solrfield:v
- field IN (v1, v2) is converted to solrfield:(v1 OR v2)
- field NOT IN (v1, v2) is converted to -solrfield:(v1 AND v2)
How functions are translated
- currentUser() is replaced by the document full name of the user
- date functions are converted to a range relative to NOW, using the following as the basis:
| date function | basis |
|---|---|
| now | NOW |
| startOfDay | NOW/DAY |
| endOfDay | NOW+DAY/DAY |
| startOfWeek | NOW/WEEK |
| endOfWeek | NOW+WEEK/WEEK |
| startOfMonth | NOW/MONTH |
| endOfMonth | NOW+MONTH/MONTH |
| startOfYear | NOW/YEAR |
| endOfYear | NOW+YEAR/YEAR |
The generated expression depends on the used operator. For instance, created > endOfDay("-3h") is converted to creationdate:{NOW+DAY/DAY-3HOURS TO *]
How the order by clause is handled
Fields in the order by clause are converted according following the previous section about field conversion. An expression suitable for the sort parameter of Solr queries is generated. The conversion is quite straightforward, as appart from the field names, the syntax between the sort parameter of Solr queries and in the CQL order by clause is the same.
Detailed examples and explanation
… that don't depend on upstream documentation are coming later. In the meantime, please look at the automated tests of the CQL Query module to know what's possible and what is not, syntactically speaking.