While working with the facets for our search result earlier today, I came across the need to limit the search against solr on one specific field in addition to our regular search string (which we run against several fields with different weights). The situation was something like this:
- Lastname
- AggregateSearchField
- AggregatePhoneticSearchField
We do the searches against the AggregateSearchField and the AggregatePhoneticSearchField, where we weight the exact match higher than the phonetic matches. This ensure that the more specific matches are ranked higher than those that are merely similiar. We do this for several different field groupings, but that’s not revelant for this post, so let’s just assume that these are the three fields relevant. We search against two of them, and uses Lastname as a facet / navigator field to allow users to get more specific with their search.
However, while users should be allowed to get more specific with their search when selecting one of the facets, it should not change their regular search. And since the dismax handler will search through all the allowed field for a given value, you cannot just append Lastname:facetValue to the search string and be done with it (dismax does not support fielded searches through the regular query). After a bit of searching through our friends over at Google, I finally stumbled across the solution (which I of course should have seen on the Solr wiki): use the fq-parameter. This allows you to submit a “Filter Query” in your request, which will be used to further filter your existing query through another set of queries. This fits very neatly in with keeping your original query and then appending filter queries for each facet limitation that gets set.
A small code example for Solrj: (filterQueries is a HashMap<String, String> which contains the facets; filterQueries.put(“Lastname”, “Smith”) will add a limitation on the field “Lastname” being “Smith” (you might want to escape “-s in the facet values)):
if (filterQueries != null)
{
for (String q : filterQueries.keySet())
{
String value = filterQueries.get(q);
query.addFilterQuery(q + ":\"" + value + "\""); // this adds Lastname:"Smith" as a filter query
}
}
So now we can just parse the query string for valid facet limitations, and set the fields in the filterQueries HashMap accordingly. As we already have a list of facet fields to include, this is a simple as iterating that list and checking for the parameters in the request variables.
A great thank you to Mike Klaas in the dismax and Plone thread indexed by nabble.com that sent me in the right direction.
Fantastic. I had the exact same shortcoming when building a query using dismax, fq saved the day, thanks for the post.
A lot of my friends have been recommending your blog of late, but I never took the time to look initially. Now that I’ve actually Having now read your work I have to say that it is very, very good and I really hope this keeps going as long as you are well enough to write. Sometimes, it helps me get through a hard day as I like to read sites I’m interested in to relax. Your site helps me to do precisely that. I am truly appreciative of that, definitely. If you don’t mind me asking, how long have you been blogging for? I’m merely wondering because I am really considering doing this myself. But really, if you don’t care to let me know, I do understand, and I wish you luck with your pursuits nonetheless. Your blog is fantastic!
Very helpful post. Is it possible to put two fields in the fq and have these treated as an “and”? For example I am trying to say approvedPost:true and created_at:[2011-12-08T00:12:01.000Z TO 2011-12-13T00:12:45.999Z]
You can apply several filters in one query, simply append another &fq= parameter to the query url. You can also combine both in the same fq, such as fq=approvedPost:true created_at:[…]