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 > '${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才是王道!
接下来实现...