使用Apache Lucene索引MySQL数据库,并使它们保持同步

  1. 在MySQL中添加新项目时,它必须也由Lucene编制索引。
  2. 当从MySQL中删除现有项时,它也必须从Lucene的索引中删除。

我们的想法是编写一个脚本,通过调度程序每隔x分钟调用一次(例如CRON任务)。 这是一种保持MySQL和Lucene同步的方法。 直到我还管理的内容:

  1. 对于MySQL中每个新添加的项目,Lucene也将其编入索引。
  2. 对于MySQL中每个已经添加的项目,Lucene不会重新索引它(没有重复的项目)。

这是我要求你帮助管理的一点:

  1. 对于之前已经从MySQL中删除的每个项目,Lucene也应该取消索引。

这是我使用的代码,它试图索引MySQL表tag (id [PK] | name)

 public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver").newInstance(); Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "root", ""); StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, analyzer); IndexWriter writer = new IndexWriter(FSDirectory.open(INDEX_DIR), config); String query = "SELECT id, name FROM tag"; Statement statement = connection.createStatement(); ResultSet result = statement.executeQuery(query); while (result.next()) { Document document = new Document(); document.add(new Field("id", result.getString("id"), Field.Store.YES, Field.Index.NOT_ANALYZED)); document.add(new Field("name", result.getString("name"), Field.Store.NO, Field.Index.ANALYZED)); writer.updateDocument(new Term("id", result.getString("id")), document); } writer.close(); } 

PS:这段代码仅供测试之用,无需告诉我它有多糟糕:)

编辑:

一种解决方案可能是删除任何预先添加的文档,并重新索引所有数据库:

 writer.deleteAll(); while (result.next()) { Document document = new Document(); document.add(new Field("id", result.getString("id"), Field.Store.YES, Field.Index.NOT_ANALYZED)); document.add(new Field("name", result.getString("name"), Field.Store.NO, Field.Index.ANALYZED)); writer.addDocument(document); } 

我不确定它是最优化的解决方案,是吗?

只要让索引/重建索引与应用程序分开运行,就会出现同步问题。 根据您的工作领域,这可能不是问题,但对于许多并发用户应用程序而言。

当我们每隔几分钟就有一个运行异步索引的作业系统时,我们遇到了同样的问题。 用户可以使用搜索引擎找到产品,然后即使管理员从有效的产品堆栈中删除了产品,仍然可以在前端找到它,直到下一个重建索引作业运行。 这导致报告给第一级支持的非常混乱且很少可重现的错误。

我们看到了两种可能性:将业务逻辑紧密地连接到搜索索引的更新,或者实现更严格的异步更新任务。 我们做了后者。

在后台,有一个类在tomcat应用程序内部的专用线程中运行,它接受更新并并行运行它们。 后台更新到前端的等待时间缩短到0.5-2秒,这大大减少了第一级支持的问题。 并且,它尽可能松散耦合,我们甚至可以实现不同的索引引擎。

看看Solr DataImportScheduler方法。
基本上,当Web应用程序启动时,会生成一个单独的Timer线程,该线程定期向Solr发出HTTP Post,然后使用您设置的DataImportHandler从RDB(和其他数据源)中提取数据。

所以,既然你没有使用Solr,只有Lucene,你应该看一下DataImportHandler来源的想法。