【问题标题】:Import data from a large CSV (or stream of data) to Neo4j efficiently in Ruby在 Ruby 中有效地将数据从大型 CSV(或数据流)导入 Neo4j
【发布时间】:2015-12-28 03:24:10
【问题描述】:

我是后台进程的新手,如果我做出错误的假设,请随时指出我。

我正在尝试编写一个脚本,将导入数据从一个大型 CSV 文件导入到 Neo4j 数据库中(将其视为数据流,无穷无尽)。 csv 文件仅包含两列 - user_a_id 和 user_b_id,它们映射有向关系。需要考虑的几点:

  1. 数据可能有重复
  2. 同一用户可以映射到多个其他用户,并且不保证它何时会再次出现。

我目前的解决方案:我正在使用 sidekiq,并让一名工作人员批量读取文件并派遣工作人员在数据库中创建边。

我遇到的问题:

  1. 由于我正在接收数据流,因此我无法对文件进行预排序并分配为一个用户建立关系的作业。
  2. 由于作业是异步执行的,如果两个工作人员正在处理同一节点的关系,我将从 Neo4j 获得一个写锁。
  3. 假设我解决了写锁问题,如果两个工作人员正在处理重复的记录,我将构建重复的边。

可能的解决方案:构建一个同步队列,并且只有一个工作人员执行写入(似乎 sidekiq 或 resque 都没有选项)。这可能会很慢,因为只有一个线程在工作。

或者,我可以编写自己的实现,它创建一个工作人员来基于 user_id(每个队列一个唯一的 id)构建多个作业队列,并使用 redis 来存储它们。然后为每个队列分配一名工作人员以写入数据库。设置队列的最大数量,这样我就不会耗尽内存,并在队列耗尽所有作业后删除队列(如果我将来看到相同的 user_id 则重新构建它)。 - 这听起来并不简单,所以我更喜欢在深入研究之前使用现有的库。

我的问题是——我可以使用现有的 gem 吗?处理此问题的良好做法是什么?

【问题讨论】:

    标签: ruby multithreading neo4j backgroundworker


    【解决方案1】:

    你有很多选择;)

    如果您的数据确实在文件中而不是流中,我绝对建议您查看 Neo4j 附带的 neo4j-import 命令。它允许您以每秒 100 万行的速度导入 CSV 数据。两个警告:您可能需要稍微修改文件格式,并且您需要生成一个新数据库(它不会将新数据导入现有数据库)

    我也会熟悉LOAD CSV 命令。这需要任何格式的 CSV,并允许您编写一些 Cypher 命令来转换和导入数据。它不如neo4j-import 快,但速度相当快,它可以从磁盘或 URL 流式传输 CSV 文件。

    由于您使用的是 Ruby,我还建议您查看neo4apis。这是我编写的一个 gem,它使批量导入数据变得更容易,这样您就不会对文件中的每个条目都发出一个请求。它允许您使用导入器在某种 DSL 中定义一个类。这些导入器可以采用任何类型的 Ruby 对象,并且给定 Ruby 对象,将使用add_nodeadd_relationship 方法定义应该导入的内容。在幕后,这会生成 Cypher 查询,这些查询会被缓冲并分批执行,这样您就不必多次往返 Neo4j。

    在考虑异步执行操作之前,我会先调查所有这些事情。但是,如果您确实有一组永无止境的数据。 MERGE 子句应该可以帮助您处理任何竞争条件或锁定。如果它们尚不存在,它允许您创建对象和关系。它基本上是find_or_create,但在数据库级别。如果您使用LOAD CSV,您可能也希望合并,而neo4apis 在幕后使用MERGE

    希望有帮助!

    【讨论】:

    • 感谢 Brian 提供的所有选项!让我看看他们,并会回复你。你提到了neo4j-import。由于它不会导入到现有数据库中,因此对于我的情况来说,这不是一个有效的选择,因为我已经有了数据库,我需要将关系部分移植到其中。不过很高兴知道!
    • 酷,乐于助人!如果您需要任何实时帮助,我是 Neo4j.rb 项目的维护者之一,我们在 Gitter 上闲逛:gitter.im/neo4jrb/neo4j
    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多