你好,游客 登录 注册 搜索
背景:
阅读新闻

开发更新Solr索引的工具

[日期:2012-05-05] 来源:Linux社区  作者:shirdrn [字体: ]

Solr搜索服务器直接部署到Web容器之中,如果想要在服务器外部管理索引(创建、更新、删除),需要向Solr服务器进程发送待处理的请求数据或者命令,实际索引变更是在Solr服务器程序中完成,自然而然底层是调用Lucene的API来实现这一操作的。为了便于平时在开发中,随时向Solr服务器发送索引更新请求,来观察实际执行状况,或验证Solr的最新功能,我们基于Solr自带的SimplePostTool,增加了聚合数据源的接口,实现了一个简易地小工具。

Solr 的详细介绍请点这里
Solr 的下载地址请点这里

工具类图

首先,我们先看一下类图及其类之间的关系,如图所示:



编码与实现


AbstractPostServer抽象类:该类表示一个要与Solr搜索服务器通信的实体,其中实现了一些与服务器基于HTTP协议进行通信的逻辑,在子类实现时,可以直接调用这些相关方法,而具体通过什么方式、以什么样的数据格式则留给子类实现。抽象类代码如下所示:

  1. package org.shirdrn.solr.tools;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7. import java.io.Serializable;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.net.HttpURLConnection;  
  10. import java.net.MalformedURLException;  
  11. import java.net.URL;  
  12. import java.util.HashSet;  
  13. import java.util.Set;  
  14.   
  15. import org.slf4j.Logger;  
  16. import org.slf4j.LoggerFactory;  
  17.   
  18. /** 
  19.  * Abstract post tool, generic operations. 
  20.  *  
  21.  * @author shirdrn 
  22.  * @date   2011-12-07 
  23.  */  
  24. public abstract class AbstractPostServer {  
  25.   
  26.     protected static final Logger LOG = LoggerFactory.getLogger(AbstractPostServer.class);  
  27.     protected URL solrUrl;  
  28.     protected PostConfig postConfig;  
  29.     protected HttpURLConnection httpConn;  
  30.     protected int responseCode = HttpURLConnection.HTTP_UNAVAILABLE;  
  31.     protected DataLoader dataLoader;  
  32.       
  33.     public AbstractPostServer(PostConfig postConfig, DataLoader dataLoader) {  
  34.         super();  
  35.         this.postConfig = postConfig;  
  36.         this.dataLoader = dataLoader;  
  37.         try {  
  38.             this.solrUrl = new URL(postConfig.postUrl);  
  39.         } catch (MalformedURLException e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.     }  
  43.       
  44.     public abstract String getResponseMessage();  
  45.       
  46.     public int getServerResponseCode() {  
  47.         return responseCode;  
  48.     }  
  49.       
  50.     protected void post(InputStream data, Integer length, OutputStream output) throws IOException {  
  51.         httpConn = (HttpURLConnection) solrUrl.openConnection();  
  52.         httpConn.setRequestMethod(postConfig.postMethod);  
  53.         httpConn.setDoOutput(true);  
  54.         httpConn.setDoInput(true);  
  55.         httpConn.setUseCaches(false);  
  56.         httpConn.setAllowUserInteraction(false);  
  57.         httpConn.setRequestProperty("Content-type", postConfig.contentType);  
  58.         if (null != length) {  
  59.             httpConn.setFixedLengthStreamingMode(length);  
  60.         }  
  61.         OutputStream out = httpConn.getOutputStream();  
  62.         pipe(data, out);  
  63.         if(out!=null) {  
  64.             out.close();  
  65.         }  
  66.         InputStream in = null;  
  67.         responseCode = httpConn.getResponseCode();  
  68.         if (HttpURLConnection.HTTP_OK != responseCode) {  
  69.             LOG.error("Solr server error: " + httpConn.getResponseCode() + " " + httpConn.getResponseMessage());  
  70.         }  
  71.         in = httpConn.getInputStream();  
  72.         pipe(in, output);  
  73.         if(httpConn!=null) {  
  74.             httpConn.disconnect();  
  75.         }  
  76.         in.close();  
  77.     }  
  78.       
  79.     private void pipe(InputStream dataIn, OutputStream dataOut) throws IOException {  
  80.         byte[] buf = new byte[1024];  
  81.         int read = 0;  
  82.         while ((read = dataIn.read(buf)) >= 0) {  
  83.             if (null != dataOut) {  
  84.                 dataOut.write(buf, 0, read);  
  85.             }  
  86.         }  
  87.         if (null != dataOut) {  
  88.             dataOut.flush();  
  89.         }  
  90.     }  
  91.       
  92.     protected InputStream stringToStream(String s) {  
  93.         InputStream is = null;  
  94.         try {  
  95.             is = new ByteArrayInputStream(s.getBytes("UTF-8"));  
  96.         } catch (UnsupportedEncodingException e) {  
  97.             e.printStackTrace();  
  98.         }  
  99.         return is;  
  100.     }  
  101.       
  102.     public void setDataLoader(DataLoader dataLoader) {  
  103.         this.dataLoader = dataLoader;  
  104.     }  
  105.   
  106.     /** 
  107.      * Solr post configuration, convenient usage. 
  108.      *  
  109.      * @author shirdrn 
  110.      * @date   2011-12-07 
  111.      */  
  112.     public static final class PostConfig implements Serializable {  
  113.         private static final long serialVersionUID = 6389419734694067683L;  
  114.         private String postUrl = "http://localhost:8080/solr/test/update";  
  115.         private String postMethod = "POST";  
  116.         private String contentType = "application/xml";  
  117.         private int maxCommitCount = 100;  
  118.         private String uniqueKey;  
  119.         private Set<String> indexFieldSet = new HashSet<String>();  
  120.         private Set<String> finalFieldSet = new HashSet<String>();  
  121.         public PostConfig(String postUrl, String postMethod, String contentType, String uniqueKey, String[] indexFields, String[] finalFields, int maxCommitCount) {  
  122.             super();  
  123.             this.postUrl = (postUrl==null ? this.postUrl : postUrl);  
  124.             this.postMethod = (postMethod==null ? this.postMethod : postMethod);  
  125.             this.contentType = (contentType==null ? this.contentType : contentType);  
  126.             this.uniqueKey = uniqueKey;  
  127.             setIndexFieldSet(indexFields);  
  128.             setFinalFieldSet(finalFields);  
  129.             this.maxCommitCount = maxCommitCount;  
  130.         }         
  131.         public int getMaxCommitCount() {  
  132.             return maxCommitCount;  
  133.         }  
  134.         public String getUniqueKey() {  
  135.             return uniqueKey;  
  136.         }  
  137.         public Set<String> getIndexFieldSet() {  
  138.             return indexFieldSet;  
  139.         }  
  140.         private void setIndexFieldSet(String[] indexFields) {  
  141.             setFieldSet(indexFields, indexFieldSet);  
  142.         }  
  143.         private void setFinalFieldSet(String[] finalFields) {  
  144.             setFieldSet(finalFields, finalFieldSet);  
  145.         }  
  146.         public Set<String> getFinalFieldSet() {  
  147.             return finalFieldSet;  
  148.         }  
  149.         private void setFieldSet(String[] finalFields, Set<String> fieldSet) {  
  150.             if(finalFields!=null) {  
  151.                 for(String field : finalFields) {  
  152.                     if(!field.isEmpty()) {  
  153.                         fieldSet.add(field.trim());  
  154.                     }  
  155.                 }  
  156.             }  
  157.         }  
  158.         @Override  
  159.         public boolean equals(Object obj) {  
  160.             PostConfig other = (PostConfig)obj;  
  161.             boolean isEquals =   
  162.                 postMethod.toLowerCase().equals(other.postMethod.toLowerCase())  
  163.                 && contentType.toLowerCase().equals(other.contentType.toLowerCase())  
  164.                 && postUrl.toLowerCase().equals(other.postUrl.toLowerCase())  
  165.                 && maxCommitCount == other.maxCommitCount  
  166.                 && indexFieldSet.equals(other.indexFieldSet)  
  167.                 && finalFieldSet.equals(other.finalFieldSet);  
  168.             return isEquals;  
  169.         }  
  170.         @Override  
  171.         public String toString() {  
  172.             StringBuffer config = new StringBuffer();  
  173.             config.append("[postUrl=" + postUrl)  
  174.                 .append(", postMethod=" + postMethod)  
  175.                 .append(", contentType=" + contentType)  
  176.                 .append(", maxCommitCount=" + maxCommitCount)  
  177.                 .append(", indexFieldSet=" + indexFieldSet)  
  178.                 .append(", finalFieldSet=" + finalFieldSet)  
  179.                 .append("]");  
  180.             return config.toString();  
  181.         }  
  182.     }  
  183.   
  184. }  
AbstractPostServer类中使用了接口DataLoader,在子类中只需要注入DataLoader接口的实现类即可以完成加载数据的功能。DataLoader接口是对不同数据源的抽象,定义如下所示:
  1. package org.shirdrn.solr.tools;  
  2.   
  3. import java.util.Map;  
  4.   
  5. public interface DataLoader {  
  6.     public Map<Object, Object> fetchOne();  
  7.     public int getRecordCount();  
  8. }  
fetchOne方法是供AbstractPostServer类的子类去调用的,每次调用获取数据源中一条记录,我们知道,在索引的时候逻辑上通常对应着一个文档(Document),如一篇文章、一段文字等等。这也就暗示了,实现DataLoader接口,必须提供一个基于数据源的迭代器,每次在fetchOne方法中调用一次迭代器(如next方法),获取到一条记录,然后在AbstractPostServer类的子类中转换成Lucene的Document(实际间接地通过Solr来转换的,而我们只是规划好每个字段及其对应的内容)。 linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款