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

2019-03-27 01:01|来源: 网路

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


转自:http://www.cnblogs.com/xuweili/articles/3685771

相关问答

更多
  • 在solr与tomcat整合文章中,我用的索引库是mycore,现在就以这个为例。 首先要准备jar包:solr-dataimporthandler-4.8.1.jar、solr-dataimporthandler-extras-4.8.1.jar和mysql-connector-java-5.0.7-bin.jar这三个包到solr的tomcat的webapps\solr\WEB-INF\lib下 在这个文件夹的conf下配置两个文件,添加一个文件。先配置solrconfig.xml。 在该文件下添加一个 ...
  • 您无需在Solr中存储原始内容。 这是存储和索引之间的区别。 如果将stored设置为false,则只会根据搜索需要保留已处理的标记化内容版本。 只需确保存储您的ID。 这是在schema.xml中的字段定义中设置的。 这意味着Solr无法将任何非存储字段返回给用户,因此您需要根据ID将它们与原始记录匹配(就像您似乎建议的那样)。 这也会破坏部分文档更新,因此您需要确保在更改内容时重新编制整个文档的索引。 You don't have to store original content in Solr. T ...
  • Solr(Lucene)使用算法从查询中返回相关文档。 它将返回一个分数以指示每个文档与查询有多相关。 它与数据库(不管是否有关系)做的不同,它返回的是匹配或不是查询的结果。 Solr (Lucene) uses an algorithm to returns relevant documents from a query. It will returns a score to indicate how relevant each document is related to the query. It i ...
  • 如果仅查询Solr是有意义的,那就这样做。 如果查询Solr某些数据是有意义的,那就这样做吧。 这取决于您的使用案例,但如果可以使用Solr中的数据回答任何查询,那么将它用于所有内容就完全没问题了。 这可能会更有效地使用您的缓存。 不,不是我所知道的。 不是真的。 Solr不太适合嵌套的JSON(即使你有父/子文档,它也是你必须在每种情况下手动处理的东西,并且需要特殊的套管)。 在这些情况下,您可以使用Solr进行查询,返回ID,然后从mongo中检索实际文档,其JSON结构完好无损。 在这种情况下,您可以 ...
  • 这是一个很好的问题,我已经深思熟虑了一些。 我将总结我的经验教训: 几乎所有情况下,您可以轻松地使用Lucene / Solr代替MongoDB,但反之亦然。 格兰特·英格索尔的帖子总结在这里。 MongoDB等似乎是一个不需要搜索和/或刻面的目的。 对于RDBMS世界的程序员来说,这似乎是一个更简单和可以说更容易的过渡。 除非有人习惯了Lucene&Solr有更陡峭的学习曲线。 没有很多使用Lucene / Solr作为数据存储的例子,但是Guardian已经取得了一些进展,并将其概括为一个很好的滑盖 , ...
  • DIH没有任何问题。 确保您的数据库连接字符串有效,并且您的数据库已启动并正在运行。 As Eric Wang pointed out I was using wrong port number and after that also I was getting SSL certificate error the final url string that worked for me is: url="jdbc:mysql://127.0.0.1:3306/indcat?useSSL=false&"
  • 是的,如果您使用的是Solr 4+,则可以将部分更新推送到Solr索引。 SCHEMA 对于部分更新, 需要存储schema.xml中的所有字段 。 这是您的fields部分在schema.xml中的样子:
  • 是的,MongoDB中的_id始终是唯一的。 它是主键,这就是为什么不需要设置UNIQUE原因。 Yes, _id in MongoDB is always unique. It's the primary key, which is why setting UNIQUE isn't necessary.
  • 正如在这个SO中所写的那样,Solr的Schemaless模式可以帮助你 Solr支持Schemaless模式 。 以这种方式启动Solr时,您最初并未绑定到架构。 当您向Solr提供第一个文档时,它将猜测相应的字段类型并生成包含这些字段类型的模式。 然后修复这些字段。 您仍然可以通过这种方式添加新字段。 你还需要做的是从你的mongodb到Solr创建某种导入路线。 谷歌搜索后,你可能会偶然发现SO问题 - MongoDB的solr数据导入处理程序 - 这也可能对你有帮助。 可能更简单的是创建一个mong ...
  • 从mongo shell中,切换到要从中收集索引的数据库 第1步:切换到现有数据库并在脚本下运行 > use my_existing_db 下面的脚本遍历所有集合并为每个集合构造一个run command 。 var database = ‘my_new_db' // SHOULD ALWAYS MATCH DESTINATION DB NAME db.getCollectionNames().forEach(function(collection){ var command = {} ...