zoukankan      html  css  js  c++  java
  • solr创建索引源码解析

    先说下创建索引源码流程

          源码类: 
              1.CommonHttpSolrServer (SolrServer的子类) 
              2.SolrServer(抽象类) 
              3.SolrRequest (基类) 
              4.AbstractUpdateRequest (抽象类、SolrRequest的子类) 
              5.UpdateRequest  (AbstractUpdateRequest的子类) 
              6.SolrInputDocument  (设置需要索引的名称和值、这个应该放在第一位) 

    创建索引代码:

      1.        查询数据库数据,或者其他文档数据进行索引
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.           private void updateBook(String sql, String url, String idColumn,  
        2.             String timeColumn,BufferedWriter dataFile) throws Exception {  
        3.         long start = System.currentTimeMillis();  
        4.                 <span></span> SolrUtil solrUtil = new SolrUtil(url);//初始化索引  
        5.         SolrDocument doc = SqlSh.getSolrMaxDoc(solrUtil, idColumn, timeColumn);  
        6.         if (doc == null) {  
        7.             CommonLogger.getLogger().error("solr no data.");  
        8.             return;  
        9.         }  
        10.         int maxId = Integer.parseInt(doc.get(idColumn).toString());  
        11.         long maxTime = Long.parseLong(doc.get(timeColumn).toString())*1000;  
        12.         Date maxDate = new Date(maxTime);  
        13.           
        14.         DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        15.                 //获取数据库需要索引的数据  
        16.         ResultSet rs = stmt_m.executeQuery(String.format(sql,  
        17.                 dateFormat2.format(maxDate)));  
        18.         //获取需要创建索引的key  
        19.                 initColumeMeta(rs.getMetaData());  
        20.   
        21.                 //解析数据并索引  
        22.         parseRs(rs, solrUtil);  
        23.   
        24.         rs.close();  
        25.                  
        26.                 //优化索引  
        27.         solrUtil.server.optimize();  
        28.   
        29.         CommonLogger.getLogger().info(  
        30.                 "update book time:" + (System.currentTimeMillis() - start)  
        31.                         / 1000 + "s");  
        32.     }  


      2. 咱们看下上面代码的parseRs方法
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. //下面是简单的解析数据方法并写索引         

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.  private void parseRs(ResultSet rs, SolrUtil solrUtil) throws <span></span> Exception {  
        2.         Collection<SolrInputDocument> docs=new ArrayList<SolrInputDocument>();  
        3.         SolrInputDocument doc = null;  
        4.         int locBk = 0;  
        5.         boolean flag=true;  
        6.         StringBuilder sb=null;  
        7.         String vl=null;  
        8.         try {  
        9.             while (rs.next()) {  
        10.                 doc = new SolrInputDocument();  
        11.                 for (int i = 0; i < ToolMain.columnNames.length; i++) {  
        12.                     doc.addField(  
        13.                         ToolMain.columnNames[i],  
        14.                         getColumnValue(  
        15.                             rs.getObject(ToolMain.columnNames[i]),  
        16.                             ToolMain.columnTypes[i]));//此方法为设置一个域,可以添加一个参数来设置权重  
        17.                 }  
        18.                 docs.add(doc);  
        19.                 locBk++;  
        20.                 if (docs.size() >= 1000) {  
        21.                     solrUtil.addDocList(docs);//创建索引和提交索引操作都在这里面  
        22.                     docs.clear();  
        23.                 }  
        24.             }  
        25.             if (docs.size() > 0) {  
        26.                 solrUtil.addDocList(docs);  
        27.                 docs.clear();  
        28.             }  
        29.         } catch (Exception e) {  
        30.             throw e;  
        31.         } finally {  
        32.             docs.clear();  
        33.             docs = null;  
        34.         }  
        35.     }  

        3.下面来说明下SolrUtil类,此类主要是封装了CommonHttpSolrServer
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. import java.util.Collection;  
        2.   
        3. import log.CommonLogger;  
        4.   
        5. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
        6. import org.apache.solr.common.SolrInputDocument;  
        7.   
        8. public class SolrUtil {  
        9.     public CommonsHttpSolrServer server = null;  
        10.   
        11.     public String url = "";//url为solr服务的地址  
        12.     public  String shards = "";  
        13.   
        14.     public SolrUtil(String url) {  
        15.         this.url = url;  
        16.         initSolr();  
        17.     }  
        18.     public SolrUtil(String url,String shards) {  
        19.         this.url = url;  
        20.         this.shards=shards;  
        21.         initSolr();  
        22.     }  
        23.        //初始化Server  
        24.     private void initSolr() {  
        25.         try {  
        26.             server = new CommonsHttpSolrServer(url);  
        27.             server.setSoTimeout(60*1000);  
        28.             server.setConnectionTimeout(60*1000);  
        29.             server.setDefaultMaxConnectionsPerHost(1000);  
        30.             server.setMaxTotalConnections(1000);  
        31.             server.setFollowRedirects(false);  
        32.             server.setAllowCompression(true);  
        33.         } catch (Exception e) {  
        34.             e.printStackTrace();  
        35.             System.exit(-1);  
        36.         }  
        37.     }  
        38.     //封装了add、commit  
        39.     public void addDocList(Collection<SolrInputDocument> docs) {  
        40.         try {  
        41.             server.add(docs);  
        42.             server.commit();  
        43.             docs.clear();//释放  
        44.         } catch (Exception e) {  
        45.             CommonLogger.getLogger().error("addDocList error.", e);  
        46.         }  
        47.     }  
        48.       
        49.     public void deleteDocByQuery(String query) throws Exception {   
        50.         try {  
        51.             server.deleteByQuery(query);  
        52.             server.commit();  
        53.         } catch (Exception e) {  
        54.             CommonLogger.getLogger().error("deleteDocByQuery error.", e);  
        55.             throw e;  
        56.         }  
        57.     }  
        58. }  

        4.现在来看看solr创建索引的源码

            其实源码执行的操作无非是 生成请求request  返回response

            1.上面代码中的SolrInputDocument 类所做的操作

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.     public class SolrInputDocument implements Map<String,SolrInputField>, Iterable<SolrInputField>, Serializable   //实现了Map和Iterable的接口并且实现了接口中的方法,其主要的类为SolrInputFiled类  

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.     public class SolrInputField implements Iterable<Object>, Serializable //类中只有三个属性,String key,Object value,还包括评分  float boost = 1.0f; 默认是1.0f(如果做权重的话可以设置这个值)  

        再来看下执行的CommonHttpSolrServer类所做的操作(表现形式在SolrUtil中的addDocList)

            2.添加文档方法

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. public UpdateResponse add(Collection<SolrInputDocument> docs )                         throws SolrServerException, IOException {  

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.             UpdateRequest req = new UpdateRequest();//创建一个request  

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.           req.add(docs);//调用UpdateRequest的add方法,添加索引文档  
        2.           return req.process(this);//亲 重点是这个方法(返回的是response)  
        3.    }  

        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.         //再看下UpdateRequest的add方法  
        2.         private List<SolrInputDocument> documents = null;  
        3.         public UpdateRequest add( final Collection<SolrInputDocument> docs )  
        4.         {  
        5.             if( documents == null ) {  
        6.                   documents = new ArrayList<SolrInputDocument>( docs.size()+1 );  
        7.             }  
        8.             documents.addAll( docs );  
        9.             return this;  
        10.         }  

         3.提交方法 commit,调用的是SolrServer类中的
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1.  public UpdateResponse commit( boolean waitFlush, boolean waitSearcher ) throws Solr    ServerException, IOException {  
        2.         return new UpdateRequest().setAction( UpdateRequest.ACTION.COMMIT, waitFlush, waitSearcher ).process( this );//看到了吗?  
        3. <pre class="java; toolbar: true; auto-links: false;"> setAction都是为了对对象ModifiableSolrParams(这个对象在最终CommonHttpSolrServerrequest的request方法中用的到)</pre>  
        4. <span></span> 在提交索引的时候也是调用的process方法  
        5.   }  

        4.优化索引
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. public UpdateResponse optimize(boolean waitFlush, boolean waitSearcher,                 int maxSegments ) throws SolrServerException, IOException {  
        2. sp;           return new UpdateRequest().setAction( UpdateRequest.ACTION.OPTIMIZE, waitFlush, waitSearcher, maxSegments ).process( this );//同样调用process,通过setAction参数,在CommonHttpSolrServer类方法request()中主要执行的是合并和压缩  setAction都是为了对对象ModifiableSolrParams(这个对象在最终CommonHttpSolrServer的request方法中用的到)进行赋值  
        3. }  

        5.既然上面都提到了process方法,那我们来看看
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. @Override  
        2.      public UpdateResponse process( SolrServer server ) throws SolrServerException,             IOException  
        3.      {  
        4.            long startTime = System.currentTimeMillis();  
        5.            UpdateResponse res = new UpdateResponse();  
        6.            res.setResponse( server.request( this ) );//这里面这个方法可是重点之重啊,这是调用了 CommonHttpSolrServer类中的request方法  
        7.            res.setElapsedTime( System.currentTimeMillis()-startTime );  
        8.            return res;  
        9.      }  

        6.最终的方法是SolrServer的子类CommonHttpSolrServer类的request方法,咋再来看看这个方法是怎么工作的
        [java] view plaincopy在CODE上查看代码片派生到我的代码片
         
        1. public NamedList<Object> request(final SolrRequest request, ResponseParser processor    ) throws SolrServerException, IOException {  
        2.       
        3.     HttpMethod method = null;  
        4.     InputStream is = null;  
        5.     SolrParams params = request.getParams();  
        6.     Collection<ContentStream> streams = requestWriter.getContentStreams(request);  
        7.     String path = requestWriter.getPath(request);  
        8.       
        9.     //创建索引进来的是/update  /select 为查询    
        10.     if( path == null || !path.startsWith( "/" ) ) {  
        11.       path = "/select";  
        12.     }  
        13.       
        14.     ResponseParser parser = request.getResponseParser();  
        15.     if( parser == null ) {  
        16.       parser = _parser;  
        17.     }  
        18.       
        19.     // The parser 'wt=' and 'version=' params are used instead of the original params  
        20.     ModifiableSolrParams wparams = new ModifiableSolrParams();  
        21.     wparams.set( CommonParams.WT, parser.getWriterType() );  
        22.     wparams.set( CommonParams.VERSION, parser.getVersion());  
        23.     if( params == null ) {  
        24.       params = wparams;  
        25.     }  
        26.     else {  
        27.       params = new DefaultSolrParams( wparams, params );  
        28.     }  
        29.       
        30.     if( _invariantParams != null ) {  
        31.       params = new DefaultSolrParams( _invariantParams, params );  
        32.     }  
        33.   
        34.     int tries = _maxRetries + 1;  
        35.     try {  
        36.       while( tries-- > 0 ) {  
        37.         // Note: since we aren't do intermittent time keeping  
        38.         // ourselves, the potential non-timeout latency could be as  
        39.         // much as tries-times (plus scheduling effects) the given  
        40.         // timeAllowed.  
        41.         try {//通过使用查看solr源码,在使用UpdateRequest对象时会自动设置为Post  
        42.           if( SolrRequest.METHOD.GET == request.getMethod() ) {  
        43.             if( streams != null ) {  
        44.                   <span></span>throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "GET can't send streams!" );  
        45.             }  
        46.             method = new GetMethod( _baseURL + path + ClientUtils.toQueryString( params, false ) );  
        47.           }  
        48.           else if( SolrRequest.METHOD.POST == request.getMethod() ) {//所以我们直接看  
        49.   
        50.             String url = _baseURL + path;  
        51.             boolean isMultipart = ( streams != null && streams.size() > 1 );  
        52.   
        53.             if (streams == null || isMultipart) {  
        54.               PostMethod post = new PostMethod(url);//设置post,包括request头部、内容、参数、等等一些操作  
        55.               post.getParams().setContentCharset("UTF-8");  
        56.               if (!this.useMultiPartPost && !isMultipart) {  
        57.                 post.addRequestHeader("Content-Type",  
        58.                     "application/x-www-form-urlencoded; charset=UTF-8");  
        59.               }  
        60.   
        61.               List<Part> parts = new LinkedList<Part>();  
        62.               Iterator<String> iter = params.getParameterNamesIterator();  
        63.               while (iter.hasNext()) {  
        64.                 String p = iter.next();  
        65.                 String[] vals = params.getParams(p);  
        66.                 if (vals != null) {  
        67.                   for (String v : vals) {  
        68.                     if (this.useMultiPartPost || isMultipart) {  
        69.                       parts.add(new StringPart(p, v, "UTF-8"));  
        70.                     } else {  
        71.                       post.addParameter(p, v);  
        72.                     }  
        73.                   }  
        74.                 }  
        75.               }  
        76.   
        77.               if (isMultipart) {  
        78.                 int i = 0;  
        79.                 for (ContentStream content : streams) {  
        80.                   final ContentStream c = content;  
        81.   
        82.                   String charSet = null;  
        83.                   PartSource source = new PartSource() {  
        84.                     public long getLength() {  
        85.                       return c.getSize();  
        86.                     }  
        87.                     public String getFileName() {  
        88.                       return c.getName();  
        89.                     }  
        90.                     public InputStream createInputStream() throws IOException {  
        91.                       return c.getStream();  
        92.                     }  
        93.                   };  
        94.                   
        95.                   parts.add(new FilePart(c.getName(), source,   
        96.                                          c.getContentType(), charSet));  
        97.                 }  
        98.               }  
        99.               if (parts.size() > 0) {  
        100.                 post.setRequestEntity(new MultipartRequestEntity(parts  
        101.                     .toArray(new Part[parts.size()]), post.getParams()));  
        102.               }  
        103.   
        104.               method = post;  
        105.             }  
        106.             // It is has one stream, it is the post body, put the params in the URL  
        107.             else {  
        108.               String pstr = ClientUtils.toQueryString(params, false);  
        109.               PostMethod post = new PostMethod(url + pstr);  
        110.   
        111.               // Single stream as body  
        112.               // Using a loop just to get the first one  
        113.               final ContentStream[] contentStream = new ContentStream[1];  
        114.               for (ContentStream content : streams) {  
        115.                 contentStream[0] = content;  
        116.                 break;  
        117.               }  
        118.               if (contentStream[0instanceof RequestWriter.LazyContentStream) {  
        119.                 post.setRequestEntity(new RequestEntity() {  
        120.                   public long getContentLength() {  
        121.                     return -1;  
        122.                   }  
        123.   
        124.                   public String getContentType() {  
        125.                     return contentStream[0].getContentType();  
        126.                   }  
        127.   
        128.                   public boolean isRepeatable() {  
        129.                     return false;  
        130.                   }  
        131.   
        132.                   public void writeRequest(OutputStream outputStream) throws IOException {  
        133.                     ((RequestWriter.LazyContentStream) contentStream[0]).writeTo(outputStream);  
        134.                   }  
        135.                 }  
        136.                 );  
        137.   
        138.               } else {  
        139.                 is = contentStream[0].getStream();  
        140.                 post.setRequestEntity(new InputStreamRequestEntity(is, contentStream[0].getContentType()));  
        141.               }  
        142.               method = post;  
        143.             }  
        144.           }  
        145.           else {  
        146.             throw new SolrServerException("Unsupported method: "+request.getMethod() );  
        147.           }  
        148.         }  
        149.         catch( NoHttpResponseException r ) {  
        150.           // This is generally safe to retry on  
        151.           method.releaseConnection();  
        152.           method = null;  
        153.           if(is != null) {  
        154.             is.close();  
        155.           }  
        156.           // If out of tries then just rethrow (as normal error).  
        157.           if( ( tries < 1 ) ) {  
        158.             throw r;  
        159.           }  
        160.           //log.warn( "Caught: " + r + ". Retrying..." );  
        161.         }  
        162.       }  
        163.     }  
        164.     catch( IOException ex ) {  
        165.       throw new SolrServerException("error reading streams", ex );  
        166.     }  
        167.   
        168.     method.setFollowRedirects( _followRedirects );  
        169.     method.addRequestHeader( "User-Agent", AGENT );  
        170.     if( _allowCompression ) {  
        171.       method.setRequestHeader( new Header( "Accept-Encoding""gzip,deflate" ) );  
        172.     }  
        173.   
        174.     try {  
        175.       // Execute the method.  
        176.       //System.out.println( "EXECUTE:"+method.getURI() );  
        177.       //执行请求,返回状态码,然后组装response 最后返回  
        178.       int statusCode = _httpClient.executeMethod(method);  
        179.       if (statusCode != HttpStatus.SC_OK) {  
        180.         StringBuilder msg = new StringBuilder();  
        181.         msg.append( method.getStatusLine().getReasonPhrase() );  
        182.         msg.append( " " );  
        183.         msg.append( method.getStatusText() );  
        184.         msg.append( " " );  
        185.         msg.append( "request: "+method.getURI() );  
        186.         throw new SolrException(statusCode, java.net.URLDecoder.decode(msg.toString(), "UTF-8") );  
        187.       }  
        188.   
        189.       // Read the contents  
        190.       String charset = "UTF-8";  
        191.       if( method instanceof HttpMethodBase ) {  
        192.         charset = ((HttpMethodBase)method).getResponseCharSet();  
        193.       }  
        194.       InputStream respBody = method.getResponseBodyAsStream();  
        195.       // Jakarta Commons HTTPClient doesn't handle any  
        196.       // compression natively.  Handle gzip or deflate  
        197.       // here if applicable.  
        198.       if( _allowCompression ) {  
        199.         Header contentEncodingHeader = method.getResponseHeader( "Content-Encoding" );  
        200.         if( contentEncodingHeader != null ) {  
        201.           String contentEncoding = contentEncodingHeader.getValue();  
        202.           if( contentEncoding.contains( "gzip" ) ) {  
        203.             //log.debug( "wrapping response in GZIPInputStream" );  
        204.             respBody = new GZIPInputStream( respBody );  
        205.           }  
        206.           else if( contentEncoding.contains( "deflate" ) ) {  
        207.             //log.debug( "wrapping response in InflaterInputStream" );  
        208.             respBody = new InflaterInputStream(respBody);  
        209.           }  
        210.         }  
        211.         else {  
        212.           Header contentTypeHeader = method.getResponseHeader( "Content-Type" );  
        213.           if( contentTypeHeader != null ) {  
        214.             String contentType = contentTypeHeader.getValue();  
        215.             if( contentType != null ) {  
        216.               if( contentType.startsWith( "application/x-gzip-compressed" ) ) {  
        217.                 //log.debug( "wrapping response in GZIPInputStream" );  
        218.                 respBody = new GZIPInputStream( respBody );  
        219.               }  
        220.               else if ( contentType.startsWith("application/x-deflate") ) {  
        221.                 //log.debug( "wrapping response in InflaterInputStream" );  
        222.                 respBody = new InflaterInputStream(respBody);  
        223.               }  
        224.             }  
        225.           }  
        226.         }  
        227.       }  
        228.       return processor.processResponse(respBody, charset);  
        229.     }  
        230.     catch (HttpException e) {  
        231.       throw new SolrServerException( e );  
        232.     }  
        233.     catch (IOException e) {  
        234.       throw new SolrServerException( e );  
        235.     }  
        236.     finally {  
        237.       method.releaseConnection();  
        238.       if(is != null) {  
        239.         is.close();  
        240.       }  
        241.     }  
        242.   }  
  • 相关阅读:
    快速幂模板
    部分有关素数的题
    POJ 3624 Charm Bracelet (01背包)
    51Nod 1085 背包问题 (01背包)
    POJ 1789 Truck History (Kruskal 最小生成树)
    HDU 1996 汉诺塔VI
    HDU 2511 汉诺塔X
    HDU 2175 汉诺塔IX (递推)
    HDU 2077 汉诺塔IV (递推)
    HDU 2064 汉诺塔III (递推)
  • 原文地址:https://www.cnblogs.com/bingbingJava/p/3625040.html
Copyright © 2011-2022 走看看