2017-10-04 138 views
2

我是Neo4j的新手,必须有一些我不了解的基础知识。Neo4j,与Cypher命令的批量加载

我在Java中有很多对象,我想用它们来填充Neo4j图形,使用Java驱动程序和Cypher。我的代码是这样的:

// 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() 
)); 

(事实上,这是稍微复杂一些,因为我有一打节点类型和大约相同数量的关系类型)。

现在,这是非常缓慢的,像加载300k节点和1M关系(在相当快的MacBookPro上,Neo4j占用12/16GB RAM)超过1小时。

我在做错误的方式吗?我应该使用batch inserter吗? (我宁愿能够通过网络访问graphDB)。我会通过将更多插入组合到一个事务中来获得某些东西吗? (从文档中,似乎事务仅用于回滚和隔离需求)。

回答

0

我来自Neo4j在Python中,但我认为这里的问题是与您的Cypher命令。我有两个建议。

单独匹配边缘可能会更快。在我的原始基准我看到24MS VS 15毫秒的这种差异(编辑:这个基准是有争议的):

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

另一种选择是使用放松。我使用BOLT接口来发送更少的事务,但不使用批处理插入器。原谅我在这里复制的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() 
+0

谢谢,但我认为它不适用于我的情况。 24-15ms没有什么不同,考虑到我的应用程序在3分钟内使用哈希映射填充内部图,而Neo4j需要很长时间才能完成。这是不对的,它应该或多或少地相同。 至于WIND,我认为发送一个列表作为参数最终会变成一个太大的查询,因为我有这么多的节点和边缘。 – zakmck

+0

我的基准可能会关闭,但我强烈建议至少尝试UNWIND。你的有效载荷列表不一定非要全部*你的数据,你可以把它整理出来(就像我在实践中做的那样,而不是上面的例子代码)。如果有效载荷的大小大约为100k,并且可以用N个交易填充边缘,那么相对于N * 100k个别交易将节省大量时间。 – sjc

+0

谢谢@sjc,我看到UNWIND上的观点,我会尝试一下。 – zakmck

0

我觉得值得报告一下我的经验。

我遵循@sjc建议并尝试使用UNWIND。然而,这并不是那么简单,因为Cypher不允许你参数化节点标签或关系类型(并且我有十几种标签和关系类型)。但最终,我能够遍历所有可能的类型,并发送足够的项目(大约1000个)到每个UNWIND块。在我看来(应该可以在一台体面的个人电脑上使用UNWIND,而且速度不够快,数百万个节点,数亿个节点不太好,或者更多),使用UNWIND的代码要快得多,但速度不够快。

插件组件速度更快(几秒钟可以上传1-2百万个节点),虽然它需要关闭HTTP访问,并且依赖于Lucene 5.4我有很多问题,因为我需要在使用Lucene 6的应用程序(产生数据)中使用,当我尝试在类路径中简单地将5.4与6交换时发生了可怕的事情。我围绕着there is some mechanism to make this possible,但它似乎并不容易,当然也没有那么好记录。

我绝对没有想到所有这些麻烦都是为了高效地执行这样的基本操作。