The ability to nest an arbitrary query type inside another query type is a useful feature that was quietly added to Solr some time ago, along with the support for query parser plugins to support different query types.I finally got around to fixing nested queries for the function query parser, and figured it was high time I documented nested queries, along with the LocalParams syntax that allows one to add metadata to a query parameter, or even change the type of a query (i.e. which query parser is used to parse the query string.) You might also be interested in: Optimizing Findability in Lucene and Solr or the Solr 1.4 Reference Guide.

Nested Queries in Lucene Syntax

To embed a query of another type in a Lucene/Solr query string, simply use the magic field name _query_.  The following example embeds a lucene query type:poems into another lucene query:

text:"roses are red" AND _query_:"type:poems"

Now of course this isn’t too useful on it’s own, but it becomes very powerful in conjunction with the query parser framework and local params which allows us to change the types of queries.  The following example embeds a DisMax query in a normal lucene query:

text:hi  AND  _query_:"{!dismax qf=title pf=title}how now brown cow"

And we can further use parameter defererencing in the local params syntax to make it easier for the front-end to compose the request:

&q=text:hi  AND  _query_:"{!dismax qf=title pf=title v=$qq}
&qq=how now brown cow

Nested Queries in Function Query Syntax

This is the part that was previously broken, and is only fixed/available in Solr 1.4.  You can use query() function to embed any other type of query in a function query, and do computations on the relevancy scores returned by that query.  Some examples from the Solr wiki are here.

Pure Nested Query

There is also a nested query parser plugin that allows one to create pure nested queries.  Is a nested query without any containing query even useful? Surprisingly yes, as it allows further decomposition of query requests. For example, the following allows an easy way for the client to specify that they want some sort of recency date boost added into the relevancy score, while leaving the exact query type up to the Solr server config (via search handler defaults in solrconfig.xml) The client query would specify the boost query as $datefunc:

q=how now brown cow&bq={!query v=$datefunc}

And the defaults for the handler in solrconfig.xml would contain the actual definition of datefunc as a function query:

<lst name="defaults">
   <str name="datefunc">{!func}recip(rord(date),1,1000,1000)</str>

The same idea could be used to allow a client to switch between complex filters, without having to specify what those filters are. Without the nested query parser type, it would only be possible to specify the query value in a separate place (via local params v=$param) not the type also.

The Future

An XML Query Parser is on the way via SOLR-839 that will allow expressing arbitrarily complex Lucene queries in XML.  As the number of query parsers grows, the importance of being able to mix, match, and nest them will become increasingly important.   One of the first extensions to the XML query parser should be to hook in nested queries of course! The subclasses of QParserPlugin show all of the query parsers currently available to Solr.  If you can’t find the query parser you’re looking for, you can create your own and register it via solrconfig.xml!    

Photo courtesy of Lori L. Stalteri (Flickr). Solr logo added.