subject: Whats A dismax? [print this page] The term dismax gets tossed around on the Solr lists frequently, which can be fairly confusing to new users. It originated as a shorthand name for the DisMaxRequestHandler (which I named after the DisjunctionMaxQueryParser, which I named after the DisjunctionMaxQuery class that it uses heavily). In recent years, the DisMaxRequestHandler and the StandardRequestHandler were both refactored into a single SearchHandler class, and now the term dismax usually refers to the DisMaxQParser.
Clear as Mudd, right?
Regardless of whether you use the DisMaxRequestHandler via the qt=dismax parameter, or use the SearchHandler with the DisMaxQParser via defType=dismax the end result is that your q parameter gets parsed by the DisjunctionMaxQueryParser.
The original goals of dismax (whichever meaning you might infer) have never changed:
supports a simplified version of the Lucene QueryParser syntax. Quotes can be used to group phrases, and +/- can be used to denote mandatory and optional clauses but all other Lucene query parser special characters are escaped to simplify the user experience. The handler takes responsibility for building a good query from the users input using BooleanQueries containing DisjunctionMaxQueries across fields and boosts you specify It also allows you to provide additional boosting queries, boosting functions, and filtering queries to artificially affect the outcome of all searches. These options can all be specified as default parameters for the handler in your solrconfig.xml or overridden the Solr query URL.
In short: You worry about what fields and boosts you want to use when you configure it, your users just give you words w/o worrying too much about syntax.
The magic of dismax (in my opinion) comes from the query structure it produces. What it essentially boils down to is matrix multiplication: a one column matrix of each chunk of your users input, multiplied by a one row matrix of the qf fields to produce a big matrix of every field:chunk permutation. The matrix is then turned into a BooleanQuery consisting of DisjunctionMaxQueries for each row in the matrix. DisjunctionMaxQuery is used because its score is determined by the maximum score of its subclauses instead of the sum like a BooleanQuery so no one word from the user input dominates the final score. The best way to explain this is with an example, so lets consider the following input.
First off, we consider the markup characters of the parser that appear in this q string:
white space dividing input string into chunk
quotes makes a single phrase chunk
+ makes a chunk mandatory
So we have 3 chunks of user input:
apache solr (must match)
search (should match)
server (should match)
With me so far right?
Where people tend to get tripped up, is in thinking about how Solrs per-field analysis configuration (in schema.xml) impacts all of this. Our example above was pretty straight forward, but lets consider for a moment what might happen if:
The name field uses the WordDelimiterFilter at query time but features do not.
The features field is configured so that the is a stopword, but name is not.
Now lets look at what we get when our input parameters are structurally similar to what we had before, but just different enough to for WordDelimiterFilter and StopFilter to come into play
The use of WordDelimiterFilter hasnt changed things very much: features is treating search-server as a single Term, while in the name field we are searching for the phrase search server hopefully this shouldnt surprise anyone given the use of WordDelimiterFilter for the name field (presumably thats why its being used). This DisjunctionMaxQuery still makes sense, but other fields with odd analysis that produce less/more Tokens then a typical field for the same thunk might produce queries that arent as easily to understand. In particular consider what has happened in our example with the word the: Because the is a stop word in the features field, no Query object is produced for that field/chunk combination. But a Query is produced for the name field, which means the total number of ShouldMatch clauses in our top level query is still 2 so our minNumberShouldMatch is still 1 (50% of 2 == 1).
This type of situation tends to confuse a lot of people: since the is a stop word in one field, they dont expect it to matter in the final query but as long as at least one qf field produces a Token for it (name in our example) it will be included in the final query, and will contribute to the count of ShouldMatch clauses.
So, whats the take away from all of this?
DisMax is a complicated creature. When using it, you need to consider all of its options carefully, and look at the debugQuery=true output while experimenting with different query strings and different analysis configurations to make really sure you understand how queries from your users will be parsed.