默认情况下,Solr查询语法只有两种形式:关键词或者以空格分隔的关键词组。当查询英文时,英文本身就是以空格来区分词的,所以Solr就能直接获取英文词并组装Query;但是中文句子中间没有空格,Solr查询时把整个句子交给Query,然后由Query再按照Field来分词、查询。这样就丧失了DisMax中qf所能带来的好处。
如果能够在用户输入之后,传入DisMax和QueryComponent之前,把中文句子分割为:关键词+空格+关键词,就能享受Solr中的所有好处。分析DisMaxQParserPlugin和DisMaxQParser的实现,在DisMaxQParser中能够获得默认查询字段和分析器,假如默认查询字段是中文类型,那么就可以通过默认字段和分析器对中文句子拆词了。
具体实现:
如果能够在用户输入之后,传入DisMax和QueryComponent之前,把中文句子分割为:关键词+空格+关键词,就能享受Solr中的所有好处。分析DisMaxQParserPlugin和DisMaxQParser的实现,在DisMaxQParser中能够获得默认查询字段和分析器,假如默认查询字段是中文类型,那么就可以通过默认字段和分析器对中文句子拆词了。
具体实现:
Solr wiki上讲得不错(http://wiki.apache.org/solr/SolrPlugins),但不具体实践一下总是有些模糊。
写自己的类,继承自QParserPlugin,主要实现parse()方法
public class MyQueryParser extends QParserPlugin {
public static final String NAME = "myParser";
@Override
public void init(NamedList args) {}
@Override
public QParser createParser(String qstr, SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
return new MyQParser(qstr, localParams, params, req);
}
public class MyQParser extends QParser {
SolrQueryParser lparser;
public MyQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
super(qstr, localParams, params, req);
}
@Override
public Query parse() throws SyntaxError {
String qstr = getString();
if (qstr == null || qstr.length()==0) return null;
String defaultField = getParam(CommonParams.DF);
if (defaultField==null) {
defaultField = getReq().getSchema().getDefaultSearchFieldName();
}
//随便写点什么
lparser = new SolrQueryParser(this, defaultField);
lparser.setDefaultOperator
(QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(),
getParam(QueryParsing.OP)));
return lparser.parse(qstr);
}
@Override
public String[] getDefaultHighlightFields() {
return lparser == null ? new String[]{} : new String[]{lparser.getDefaultField()};
}
}
}
在solrconfig.xml中注册queryParser
<queryParser name="myParser" class="org.apache.solr.parser.MyQParserPlugin"/>
将这个parser设置为默认的parser
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="defType">myParser</str>
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>
</lst>
</requestHandler>
修改了示例中”/select”的配置,可以做到长期透明地使用这个自定义的Parser