Neo4J,带有Cypher命令的散装负载



我是neo4j的新手,对基础知识一定不了解。

我在Java中有许多对象,我想使用Java驱动程序和Cypher使用它们来填充Neo4J图。我的代码正常工作:

// nodes
for ( Person person: persons )
  session.run ( String.format ( 
    "CREATE ( :Person { id: '%s', name: "%s", surname: "%s" })",
    person.getId(), person.getName(), person.getSurname ()
  ));
// relations
session.run ( "CREATE INDEX ON :Person(id)" );
for ( Friendship friendship: friendships )
  session.run ( String.format ( 
    "MATCH ( from:Person { id: '%s' } ), ( to:Person { id: '%s' } )n" +
    "CREATE (from)-:KNOWS->(to)n",
    friendship.getFrom().getId(), 
    friendship.getTo().getId() 
  )); 

(实际上,它更复杂,因为我有十二个节点类型,并且数量相同的关系类型)。

现在,这非常慢,就像1小时以上的加载300K节点和1M关系(在MacBookPro中,Neo4J摄入12/16GB的RAM)。

我做错了吗?我应该使用批次插入器吗?(我希望能够通过网络访问GraphDB)。我会通过将更多插入插入一项交易来获得一些东西吗?(从文档中,交易似乎仅对返回和隔离需求有用)。

我来自python的neo4j,但我认为这里的问题是您的cypher命令。我有两个建议。

分别匹配边缘可能更快。在我的原始基准测试上,我看到与此相差24ms vs 15ms(编辑:此基准值可疑):

MATCH ( from:Person { id: '%s' } )
MATCH ( to:Person { id: '%s' } )
CREATE (from)-:KNOWS->(to)

另一个选择是使用Undind。我将其与螺栓接口一起发送,以发送更少的交易,但不使用批处理插入器。请原谅我在这里复制的Python实现,希望您可以将其与JavaScript Neo4J驱动程序文档一起进行转换。

payload = {"list":[{"a":"Name1","b":"Name2"},{"a":"Name3","b":"Name4"}]}
statement = "UNWIND {list} AS d "
statement += "MATCH (A:Person {name: d.a}) "
statement += "MATCH (B:Person {name: d.b}) " 
statement += "MERGE (A)-[:KNOWS]-(B) "
tx = session.begin_transaction()
tx.run(statement,payload)
tx.commit()

我认为在此上报告我的经验是值得的。

我已经遵循@SJC建议,并尝试了放松。但是,这并不是那么简单,因为Cypher不允许您参数性节点标签或关系类型(我有十几个标签和关系类型)。但是最终,我能够循环所有可能的类型,并将足够的项目(约1000个)发送到每个放松的块。

我认为,使用Undind的代码更快但不够快(在我看来应该可以在不错的PC上可以使用,并且有几百万个节点,而不是很棒的,而不是很棒的数以千计的节点或更多节点)。

插入器组件要快得多(上传1-200万节点几秒钟),尽管它需要将HTTP访问降低,并且我对Lucene 5.4的依赖性遇到了很多问题,因为我需要在使用Lucene 6的应用程序(生成数据)中使用它,而当我尝试将5.4与6中的6交换时,发生了可怕的事情。我读过,有一些机制可以实现这一目标,但是看起来并不容易,而且肯定没有得到很好的文献记载。

我绝对没想到有效执行这样的基本操作的所有这些麻烦。

最新更新