solr&lucene3.6.0源碼解析(四)

本文要描述的是solr的查詢插件,該查詢插件目的用於生成Lucene的查詢Query,相似於查詢條件表達式,與solr查詢插件相關UML類圖以下:html

若是咱們強行將上面的類圖歸入某種設計模式語言的話,本人姑且將之納入橋接模式(Bridge)吧;QParserPlugin插件的行爲依賴於QParser的具體類型web

QParserPlugin爲抽象類,職責爲建立QParser類型對象apache

package org.apache.solr.search;

import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;

public abstract class QParserPlugin implements NamedListInitializedPlugin {
  /** internal use - name of the default parser */
  public static String DEFAULT_QTYPE = LuceneQParserPlugin.NAME;

  /** internal use - name to class mappings of builtin parsers */
  public static final Object[] standardPlugins = {
    LuceneQParserPlugin.NAME, LuceneQParserPlugin.class,
    OldLuceneQParserPlugin.NAME, OldLuceneQParserPlugin.class,
    FunctionQParserPlugin.NAME, FunctionQParserPlugin.class,
    PrefixQParserPlugin.NAME, PrefixQParserPlugin.class,
    BoostQParserPlugin.NAME, BoostQParserPlugin.class,
    DisMaxQParserPlugin.NAME, DisMaxQParserPlugin.class,
    ExtendedDismaxQParserPlugin.NAME, ExtendedDismaxQParserPlugin.class,
    FieldQParserPlugin.NAME, FieldQParserPlugin.class,
    RawQParserPlugin.NAME, RawQParserPlugin.class,
    TermQParserPlugin.NAME, TermQParserPlugin.class,
    NestedQParserPlugin.NAME, NestedQParserPlugin.class,
    FunctionRangeQParserPlugin.NAME, FunctionRangeQParserPlugin.class,
    SpatialFilterQParserPlugin.NAME, SpatialFilterQParserPlugin.class,
    SpatialBoxQParserPlugin.NAME, SpatialBoxQParserPlugin.class,
  };

  /** return a {@link QParser} */
  public abstract QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req);
}

LuceneQParserPlugin類繼承自QParserPlugin抽象類,爲Solr3.6.0的默認QParserPlugin插件設計模式

/**
 * Parse Solr's variant on the Lucene QueryParser syntax.
 * <br>Other parameters:<ul>
 * <li>q.op - the default operator "OR" or "AND"</li>
 * <li>df - the default field name</li>
 * </ul>
 * <br>Example: <code>{!lucene q.op=AND df=text sort='price asc'}myfield:foo +bar -baz</code>
 */
public class LuceneQParserPlugin extends QParserPlugin {
  public static String NAME = "lucene";

  public void init(NamedList args) {
  }

  @Override
  public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
    return new LuceneQParser(qstr, localParams, params, req);
  }
}

class LuceneQParser extends QParser {
  SolrQueryParser lparser;

  public LuceneQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
    super(qstr, localParams, params, req);
  }


  @Override
  public Query parse() throws ParseException {
    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);

    // these could either be checked & set here, or in the SolrQueryParser constructor
    String opParam = getParam(QueryParsing.OP);
    if (opParam != null) {
      lparser.setDefaultOperator("AND".equals(opParam) ? QueryParser.Operator.AND : QueryParser.Operator.OR);
    } else {
      // try to get default operator from schema
      QueryParser.Operator operator = getReq().getSchema().getSolrQueryParser(null).getDefaultOperator();
      lparser.setDefaultOperator(null == operator ? QueryParser.Operator.OR : operator);
    }

    return lparser.parse(qstr);
  }


  @Override
  public String[] getDefaultHighlightFields() {
    return lparser == null ? new String[]{} : new String[]{lparser.getField()};
  }
  
}
}

其中LuceneQParser類爲LuceneQParserPlugin類的內部類,繼承自QParser抽象類,其職責爲建立Lucene的Query對象app

QParser抽象類,其中的靜態方法getParser獲取具體的QParser類型對象供RequestHandler處理器調用ide

/** Create a <code>QParser</code> to parse <code>qstr</code>,
   * assuming that the default query type is <code>defaultType</code>.
   * The query type may be overridden by local parameters in the query
   * string itself.  For example if defaultType=<code>"dismax"</code>
   * and qstr=<code>foo</code>, then the dismax query parser will be used
   * to parse and construct the query object.  However
   * if qstr=<code>{!prefix f=myfield}foo</code>
   * then the prefix query parser will be used.
   */
  public static QParser getParser(String qstr, String defaultType, SolrQueryRequest req) throws ParseException {
    // SolrParams localParams = QueryParsing.getLocalParams(qstr, req.getParams());

    String stringIncludingLocalParams = qstr;
    SolrParams localParams = null;
    SolrParams globalParams = req.getParams();
    boolean valFollowedParams = true;
    int localParamsEnd = -1;

    if (qstr != null && qstr.startsWith(QueryParsing.LOCALPARAM_START)) {
      Map<String, String> localMap = new HashMap<String, String>();
      localParamsEnd = QueryParsing.parseLocalParams(qstr, 0, localMap, globalParams);

      String val = localMap.get(QueryParsing.V);
      if (val != null) {
        // val was directly specified in localParams via v=<something> or v=$arg
        valFollowedParams = false;
      } else {
        // use the remainder of the string as the value
        valFollowedParams = true;
        val = qstr.substring(localParamsEnd);
        localMap.put(QueryParsing.V, val);
      }
      localParams = new MapSolrParams(localMap);
    }


    String type;
    
    if (localParams == null) {
      type = defaultType;
    } else {
      type = localParams.get(QueryParsing.TYPE,defaultType);
      qstr = localParams.get("v");
    }

    type = type==null ? QParserPlugin.DEFAULT_QTYPE : type;

    QParserPlugin qplug = req.getCore().getQueryPlugin(type);
    QParser parser =  qplug.createParser(qstr, localParams, req.getParams(), req);

    parser.stringIncludingLocalParams = stringIncludingLocalParams;
    parser.valFollowedParams = valFollowedParams;
    parser.localParamsEnd = localParamsEnd;
    return parser;
  }

SolrQueryParser繼承自Lucene的QueryParser,職責爲解析查詢表達式,生成查詢Query對象(重寫了父類QueryParser的部分方法)post

--------------------------------------------------------------------------- ui

本系列solr&lucene3.6.0源碼解析系本人原創 this

轉載請註明出處 博客園 刺蝟的溫馴 spa

本人郵箱: chenying998179#163.com (#改成@)

本文連接http://www.cnblogs.com/chenying99/p/3508509.html

相關文章
相關標籤/搜索