Design of the CQL query module

Last modified by Raphaël Jakse on 2026/03/23 14:50

Explanation

For the design of the CQL module as a whole, see Design of the CQL module.

General considerations

In Confluence, CQL is tightly connected to its search feature. One can typically perform an advanced search using a CQL query. CQL fields typically looks like fields indexed by something like something like Lucene / Solr or Elastic Search, as opposed like a SQL / hibernate database, which would be typically lower level. Atlassian documentation hints at Lucene:

 You can use the CONTAINS operator to use Lucene's text-searching features when performing searches on these

Luckily, XWiki is quite similar to Confluence in being written in Java and using a similar architecture especially when it comes to search. In XWiki, we use Solr, which is backed by Lucene.

Consequently, we chose to implement CQL support with a conversion to Solr expression, which is likely similar to what Confluence does as well. The main difficulty is that we obviously don't use the same indexed document schema, and we don't even have the same fields or the same exact concepts (see xwiki-equivalence for more information on this), so the conversion is not straightforward. We don't have a 1:1 mapping between CQL fields and fields we have in XWiki's Solr indexed documents. Fortunately, it's close enough for the more used features.

The CQL query executor

The CQL Query module implements org.xwiki.query.QueryExecutor with the name cql, which makes it possible to instanciate a org.xwiki.query.Query object with a cql type and a cql expression and execute this query like any other query or any supported type.

This query executor:

  1. parses the query using the AQL parser (see its design)
  2. converts the resulting abstract syntax tree to a Solr query
  3. executes the Solr query.

For the end user, executing a CQL query is exactly like executing a Solr query, notably with the same kind of results.

The CQL to Solr conversion

The CQL to Solr conversion is done by the CQLToSolrQueryConverter component. The general idea is that this component and all the components implementing CQLToSolrAtomConverter has a convertToSolr method that returns a solr sub-expression for each AQL AST node type that can be converted to a solr sub-expression.

It was decided to make the conversion modular and extensible because CQL itself can be extended in Confluence: Confluence plugins can add fields that can be queried from CQL. Making the conversion modular on our side allows XWiki extensions that would implement the features of such CQL plugins to also "make the CQL part work".

Basically, extensions can implement their own CQLToSolrAtomConverter, typically by extending DefaultCQLToSolrAtomConverter which makes this work way easier.

To see how this works in practice, please see Query.

Get Connected