君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理
默认情况下,Solr查询语法只有两种形式:关键词或者以空格分隔的关键词组。当查询英文时,英文本身就是以空格来区分词的,所以Solr就能直接获取英文词并组装Query;但是中文句子中间没有空格,Solr查询时把整个句子交给Query,然后由Query再按照Field来分词、查询。这样就丧失了DisMax中qf所能带来的好处。 

如果能够在用户输入之后,传入DisMax和QueryComponent之前,把中文句子分割为:关键词+空格+关键词,就能享受Solr中的所有好处。分析DisMaxQParserPlugin和DisMaxQParser的实现,在DisMaxQParser中能够获得默认查询字段和分析器,假如默认查询字段是中文类型,那么就可以通过默认字段和分析器对中文句子拆词了。 

具体实现: 

修改solrconfig.xml 

增加一行:<queryParser name="myDisMax" class="my.MyQParserPlugin"/> 

增加类MyQParserPlugin 

public class MyQParserPlugin extends QParserPlugin { 
  public static String NAME = "myDisMax"; 
  public void init(NamedList args) { 
  } 
  public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) { 
    return new MyQParser(qstr, localParams, params, req); 
  } 


增加类MyQParser 

public class MyQParser extends DisMaxQParser { 
  private static Logger log = LoggerFactory.getLogger(MyQParser.class); 
  public MyQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) { 
    super(qstr, localParams, params, req); 
    Analyzer analyzer = req.getSchema().getQueryAnalyzer(); 
    if(null == analyzer) 
        return; 
    StringBuilder norm = new StringBuilder(); 
log.info("before analyzer, qstr="+this.qstr); 
    try{ 
        TokenStream tokens = analyzer.reusableTokenStream( req.getSchema().getDefaultSearchFieldName(), new StringReader( this.qstr ) ); 
        tokens.reset(); 
        Token token = tokens.next(); 
        while( token != null ) { 
          norm.append( new String(token.termBuffer(), 0, token.termLength()) ).append(" "); 
          token = tokens.next(); 
        } 
    } catch(Exception ex){ 
log.info("Ex="+ex); 
    } 
    if(norm.length() > 0) 
        this.qstr = norm.toString(); 
log.info("after analyzer, qstr="+this.qstr); 
  } 
posted on 2012-07-28 20:21  刺猬的温驯  阅读(1399)  评论(0编辑  收藏  举报