`

Solr 创建索引的原理 源码分析

    博客分类:
  • solr
阅读更多

本次分析以Solr3.3是最新的版本为准,
Solr3.3接收客户端的查询索引,新建索引请求都是通过过滤器SolrDispatchFilter来提交给SolrCore的Eexecute方法的。而WEB
.xml文件里的Servlet都不取作用的。SolrDispatchFilter主要是根据当前请求路径的PATH,客户端发起的请求PATH主要如下几类:

1 /admin 以adinm开头的则到Solr的管理页面。

2 /select,/update 这类的为对应的Handler  /select 即搜索请求,对应的handler为 SearchHandler,/update新建,更新索引对应的handler为XmlUpdateRequestHandler,这里主要讲一下 Solr是怎么对新建索引的XML格式的请求做解析的。
新建索引的命令如下:
<add><doc boost=2.1><field name="id">222</field></doc></add>
XmlUpdateRequestHandler 类是ContentStreamHandlerBase的子类,处理的方法在ContentStreamHandlerBase类的
handleRequestBody方法,该方法的代码有:
//创建一个xml的解析器,实类为XMLLoader XMLLoader继承抽象的ContentStreamLoader
ContentStreamLoader documentLoader = newLoader(req, processor);

documentLoader.load(req, rsp, stream);//开始读取要创建的doc信息。
主要代码如下:

对<add>标签的处理如下:
          String currTag = parser.getLocalName();
          if (currTag.equals(XmlUpdateRequestHandler.ADD)) {
            XmlUpdateRequestHandler.log.trace("SolrCore.update(add)");
            addCmd = new AddUpdateCommand();
            boolean overwrite = true;  // the default
            Boolean overwritePending = null;
            Boolean overwriteCommitted = null;
            //判断add标签是否有其他的属性,主要包过如下几个:
            //overwrite,allowDups,commitWithin,overwritePending,overwriteCommitted
            for (int i = 0; i < parser.getAttributeCount(); i++) {
              String attrName = parser.getAttributeLocalName(i);
              String attrVal = parser.getAttributeValue(i);
              if (XmlUpdateRequestHandler.OVERWRITE.equals(attrName)) {
                overwrite = StrUtils.parseBoolean(attrVal);
              } else if (XmlUpdateRequestHandler.ALLOW_DUPS.equals(attrName)) {
                overwrite = !StrUtils.parseBoolean(attrVal);
              } else if (XmlUpdateRequestHandler.COMMIT_WITHIN.equals(attrName)) {
                addCmd.commitWithin = Integer.parseInt(attrVal);
              } else if (XmlUpdateRequestHandler.OVERWRITE_PENDING.equals(attrName)) {
                overwritePending = StrUtils.parseBoolean(attrVal);
              } else if (XmlUpdateRequestHandler.OVERWRITE_COMMITTED.equals(attrName)) {
                overwriteCommitted = StrUtils.parseBoolean(attrVal);
              } else {
                XmlUpdateRequestHandler.log.warn("Unknown attribute id in add:" + attrName);
              }
            }
            // check if these flags are set
            if (overwritePending != null && overwriteCommitted != null) {
              if (overwritePending != overwriteCommitted) {
                throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                        "can't have different values for 'overwritePending' and 'overwriteCommitted'");
              }
              overwrite = overwritePending;
            }
           //通过下面三行代码,起作用的就是overwrite
            addCmd.overwriteCommitted = overwrite;
            addCmd.overwritePending = overwrite;
            addCmd.allowDups = !overwrite;

对<doc>标签的处理如下:
else if ("doc".equals(currTag)) {
            XmlUpdateRequestHandler.log.trace("adding doc...");
            addCmd.clear();
            addCmd.solrDoc = readDoc(parser);
}
readDoc方法主要是读取<doc>标签和<field>的读取<doc>代码如下:
     //Solr 把Luence的Doc封装为SolrInputDocument
     SolrInputDocument doc = new SolrInputDocument();
    String attrName = "";
    for (int i = 0; i < parser.getAttributeCount(); i++) {
      attrName = parser.getAttributeLocalName(i);
      if ("boost".equals(attrName)) {
        doc.setDocumentBoost(Float.parseFloat(parser.getAttributeValue(i)));
      } else {
        XmlUpdateRequestHandler.log.warn("Unknown attribute doc/@" + attrName);
      }
    }
   从上面的代码可以看出,<doc>标签可以有属性boost,(<doc boost="2">)即可以给该doc设置权重。以改变评分。
读取field的代码就不贴了,相信读者也会想到和上面的是一个模式,会读取 field的name,boost,属性,像<doc>一样,
我们也可以给特定的field设置权重。遇到</field>标签时,代码如下:
              doc.addField(name, text.toString(), boost);
              boost = 1.0f;
从上面两行代码可以看出,每一个field字段默认的boost为1.0.
Solr解析完<add>命令,创建一个SolrInputDocument  对象,那Solr是怎么把SolrInputDocument 对象转变为luence
的doc对象的呢,在创建时,Solr创建了一个process 这个process是RunUpdateProcessor的实例,上面readDoc方法完成后,返回SolrInputDocument  实例,然后调用RunUpdateProcessor的processAdd方法。把SolrInputDocument  对象转变为luence
doc对象。代码如下:
    public void processAdd(AddUpdateCommand cmd) throws IOException {
         //转变doc对象
         cmd.doc = DocumentBuilder.toDocument(cmd.getSolrInputDocument(), req.getSchema());
         //主要是把luence doc写到内存索引
         updateHandler.addDoc(cmd);
         super.processAdd(cmd);
  }

分享到:
评论
2 楼 zkq-java 2012-08-16  
zkq-java 写道
[u][/u]
引用
[i][/i]

    [*]
[img][/img][url][/url][flash=200,200][/flash]
[color=darkred][/color][size=x-small][/size][align=right][/align]

1 楼 zkq-java 2012-08-16  
[u][/u]
引用
[i][/i]

    [*]
[img][/img][url][/url][flash=200,200][/flash]
[color=darkred][/color][size=x-small][/size][align=right][/align]

相关推荐

Global site tag (gtag.js) - Google Analytics