1, Solr合并索引数据有两种方法,第一种是1.4版本中引入的,通过CoreAdminHandler来实现,示例如下: http://localhost:8983/solr/admin/cores?action=mergeindexes&core=core0&indexDir=/opt/solr/core1/data/index&indexDir=/opt/solr/core2/data/index 上述命令会将core1和core2的索引合并到core0中去,这里最值得注意的一点是:一旦合并完成,必须在core0上调用commit操作,否则索引数据的变化对于searchers来说是暂时不可见的,只有等到下次core0重新装载起来时才可见。 实现代码如下:

 
  
  1. /**  
  2.  * 合并索引数据 
  3.  * @param otherIndexPathList 其他待合并的索引数据路径 
  4.  * @param coreName 合并的目标solr核名称 
  5.  *  
  6.  */    private void mergeIndexData(List<String> otherIndexPathList, String coreName) { 
  7.     if (null != otherIndexPathList && otherIndexPathList.size() > 0) { 
  8.         HttpClient client = new HttpClient(); 
  9.         client.setConnectionTimeout(20000); 
  10.         client.setTimeout(20000); 
  11.         client.setHttpConnectionFactoryTimeout(20000); 
  12.          
  13.         StringBuffer sb = new StringBuffer(); 
  14.         for (int i = 0; i < otherIndexPathList.size(); ++i) { 
  15.             sb.append("&indexDir=" + otherIndexPathList.get(i) + "/data/index"); 
  16.         } 
  17.         String mergeIndexCMD = "http://" + Constants.LOCAL_ADDRESS + ":" + this.port  + "/admin/cores?action=mergeindexes&core="+ coreName; 
  18.         if (sb.length() > 0) { 
  19.             mergeIndexCMD += sb.toString(); 
  20.         } 
  21.         HttpMethod method = new GetMethod(mergeIndexCMD); 
  22.         method.getParams().setContentCharset("GBK"); 
  23.         method.getParams().setHttpElementCharset("GBK"); 
  24.         method.getParams().setCredentialCharset("GBK"); 
  25.  
  26.         // execute the method. 
  27.         try { 
  28.             if (client.executeMethod(method) == 200) { 
  29.                 String response = method.getResponseBodyAsString(); 
  30.                 if (logger.isInfoEnabled()) { 
  31.                     logger.info("merge result" + response); 
  32.                 } 
  33.             } 
  34.         } catch (Exception e) { 
  35.             logger.error("合并其他索引数据失败 " + coreName + ",索引目录: " + otherIndexPathList, e); 
  36.         } 
  37.          
  38.         //commit操作让合并后的索引对搜索生效 
  39.         StreamingUpdateSolrServer httpSolrServer = null
  40.         httpSolrServer = getSolrServer(Constants.LOCAL_ADDRESS, this.port, coreName);  
  41.         try { 
  42.             httpSolrServer.commit(); 
  43.         } catch (Exception e) { 
  44.         } 
  45.     } 
  46.          

 第二种方法是Solr3.3中引入的,也是通过CoreAdminHandler来实现,示例如下:

http://localhost:8983/solr/admin/cores?action=mergeindexes&core=core0&srcCore=core1&srcCore=core2

      同第一种方法一样,一旦合并完成,必须在core0上调用commit操作,否则索引数据的变化对于searchers来说是暂时不可见的,只有等到下次core0重新装载起来时才可见。

      使用”srcCore”和”indexDir”这两种方法的区别:

1)    使用”indexDir”参数,你可以合并不是与Solr核相关联的索引数据,比如通过Lucene直接创建的索引

2)    使用”indexDir”参数,你必须注意索引数据不是直接写入的,这就意味着如果它是一个solr核的索引,必须要关闭IndexWriter,这样才能触发一个commit命令。

3)    “indexDir”必须指向solr核所在的主机上的磁盘路径,这就限制比较多了,而相反,你可以只给srcCore一个solr核的名称,而不关心它的实际索引路径在哪。

4)    使用”srcCore”,你必须确保即使源索引数据同时存在写操作的时候,合并后的索引页不会损坏。

 

2,   solr索引合并的时候,底层其实调用的还是Lucene,因此你schema.xml中配置的uniqueKeys它并不知道,因此当你对两个包含相同文档(由uniqueKey确定)的索引进行合并时,你会得到双倍的文档数,solr这个地方应该改下,毕竟你不是简单的Lucene包装嘛。。。