Solr从Mongodb索引数据(上) 借助mongodb-jdbc和配置JdbcDataSource

Mongodb越来越流行,这边也用Mongodb去存储大量数据.但碰到一个问题,如何通过Solr从Mongodb中获取数据以及索 引?Mongodb提供了DataImportHandler去索引数据,目前支持以下几种数据来 源:JdbcDataSource,ContentStreamDataSource,FieldReaderDataSource,MockDataSource,URLDataSource
用得比较多的还是JdbcDataSource,Solr对它的支持也比较完善,如增量索引.但Mongodb并不支持JDBC(貌似也不可能支持),提供了自己的
Driver:mongo-java-driver,下载地址:https://github.com/mongodb/mongo-java-driver/downloads.
但由于之前项目较紧,自己写个针对Mongodb的DataImportHandler又来不及.于是google下下,找到了mongo-jdbc.下载地址:https://github.com/erh/mongo-jdbc

mongo-jdbc估计就是个翻译,将mongo-java-driver翻译成JDBC,如连接,查询,插入等.自己也没来得及细看.但集成 到Solr中还是发现一些问题,因为Solr中利用JDBC的一些特性mongo-jdbc并不支持,无奈只能修改部分源码来赶鸭子上架.但这也只是权宜 之计,等时间充沛再针对mongodb写一个DataImportHandler吧.

这里先说明下如何使用:
1.建立db-data-config.xml,我这边示例如下:

<dataConfig>
     <dataSource driver="com.mongodb.jdbc.MongoDriver" url="mongodb://192.168.1.166/tapp" autoCommit="true"/>
     <document>
        <entity name="ziyuan" query="select id,name,content, tags from source"
deltaQuery="select id,name,content, tags from item where addTime &gt; '${dataimporter.last_index_time}'">
           <field column="_id" name="myid" />
           <field column="name" name="name" />
           <field column="content" name="content" />
           <field column="tags" name="tags" />
      </entity>
   </document>
</dataConfig>

主要修改dataSource中driver,url.其他基本类似.

2.如此就可以运行了,在浏览器中输入导入http请求,如:http://localhost:8080/solr1.4/core0/dataimport?command=full-import
但发现会报一系列错误.这也是我以上提的,Solr中需要JDBC一些特性,但mongo-jdbc中并不支持.这只能修改源码了.修改地方如下,
主要修改两个类,一个是Solr中的JdbcDataSource,另外一个是mongo-jdbc中的MongoResultSet:
1)org.apache.solr.handler.dataimport.JdbcDataSource
a) 需要替换一个地方,具体看注释

protected Callable<Connection> createConnectionFactory(final Context context, final Properties initProps) {
  // 略
  if (url != null) {
    // 郭芸修改,不支持MongoDB
    // 将c = DriverManager.getConnection(url, initProps)替换成如下
    //c = DriverManager.getConnection(url, initProps);
    if(url.startsWith("mongodb:")){
      c=DriverManager.getConnection(url);
    }else{
      c = DriverManager.getConnection(url, initProps);
    }
  }
  // 略
}

b) 需要替换三个地方,具体请看注释

private class ResultSetIterator {
  // 略
  public ResultSetIterator(String query) {
    // 略
    Connection c = getConnection();
    // 郭芸修改,MongoDB暂还不支持
    // stmt = c.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY); 替换成如下
    /*stmt = c.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);*/
   stmt = c.createStatement();
    // 略
    // 郭芸修改,MongoDB-JDBC暂还不支持
    // 替换以下注释语句
    /*if (stmt.execute(query)) {
      resultSet = stmt.getResultSet();
    }*/
    resultSet=stmt.executeQuery(query);
    // 略
    // 郭芸修改,MongoDB-JDBC还不支持元数据
    // 替换以下注释语句
    //colNames = readFieldNames(resultSet.getMetaData());
    if(resultSet instanceof MongoResultSet){
      MongoResultSet rs=(MongoResultSet)resultSet;
      colNames=rs.getColNames();
    }else{
      colNames = readFieldNames(resultSet.getMetaData());
    }
  }
}


2)com.mongodb.jdbc.MongoResultSet
a)需要增加一个方法,具体如下:

// 郭芸修改,以便可以获取Field Name,solr中JdbcDataSource需要根据Filed name来匹配以及获取数据
public List<String> getColNames(){
  List colNames=new ArrayList();
  String colName;
  for(int i=1;i<=_fields._ids.size();i++){
    colName=this._find(i);
    // 由于Mongodb中的id为_id,所以需要替换,否则无法获取id数据
    if(colName.equals("id")){
      colName="_id";
    }
    colNames.add(colName);
    }
  return colNames;
}

最后将修改的类重新编译打包替换之前的包便可运行,我这边运行通过.但增量索引还未验证.
看来还是要自己实现一个DataImportHandler才是王道!
接下来实现...

posted @ 2014-04-24 16:04  山顶的鱼  阅读(1710)  评论(0编辑  收藏  举报