Custom Solr QueryParsers for fun and profit
Posted by Kelvin on 09 Sep 2013 at 02:53 pm | Tagged as: Lucene / Solr / Elasticsearch / Nutch
In this post, I'll show you what you need to do to implement a custom Solr QueryParser.
Step 1
Extend QParserPlugin.
public class TestQueryParserPlugin extends QParserPlugin { public void init(NamedList namedList) { } @Override public QParser createParser(String s, SolrParams localParams, SolrParams params, SolrQueryRequest req) { return new TestQParser(s, localParams, params, req); } }
This is the class you'll define in solrconfig.xml, informing Solr of your queryparser. Define it like so:
<queryParser name="myfunparser" class="org.supermind.solr.queryparser.TestQParserPlugin"/>
Step 2
Extend QParser.
public class TestQParser extends QParser { public TestQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) { super(qstr, localParams, params, req); } @Override public Query parse() throws SyntaxError { return null; } }
Step 3
Actually implement the parsing in the parse() method.
Suppose we wanted to make a really simple parser for term queries, which are space-delimited. Here's how I'd do it:
@Override public Query parse() throws SyntaxError { String defaultField = req.getSchema().getDefaultSearchFieldName(); QueryParser.Operator defaultOperator = QueryParser.Operator.valueOf(req.getSchema().getQueryParserDefaultOperator()); BooleanClause.Occur op = (defaultOperator == QueryParser.Operator.AND) ? BooleanClause.Occur.MUST : BooleanClause.Occur.SHOULD; String[] arr = qstr.split(" "); BooleanQuery bq = new BooleanQuery(true); for(String s: arr) { if(s.trim().length() == 0) continue; bq.add(new TermQuery(new Term(defaultField, s)), op); } return bq; }
Step 4
In your query, use the nested query syntax to call your queryparser, e.g.
http://localhost:8983/solr/collection1/select?q={!myfunparser}foo+bar+car
Maybe in a follow-up post, I'll post the full code with jars and all.