我是Neo4j的新手,必须有一些我对基础知识不了解的东西。
我在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关系超过1小时(在相当快的MacBookPro上,Neo4j占用12 / 16GB RAM)。
我做错了吗?我应该使用batch inserter吗? (我希望能够通过网络访问graphDB)。我会通过将更多插入分组到一个事务中来获得某些东西吗? (从文档中看,事务似乎只对回滚和隔离需求有用)。
答案 0 :(得分:0)
我来自Python中的Neo4j,但我认为这里的问题是你的Cypher命令。我有两个建议。
分别匹配边缘可能会更快。在我的原始基准测试中,我看到24ms与15ms相差(编辑:这个基准是可疑的):
SiteSelectionViewController *sitesController;
sitesController = [[SiteSelectionViewController alloc] init];
[sitesController setConfData:self.confData];
[sitesController setConfInitData:self.confInitData];
[self.navigationController pushViewController:sitesController animated:YES];
[sitesController release];
另一种选择是使用UNWIND。我在BOLT接口中使用它来发送更少的事务但不使用批量插入器。原谅我在这里复制的Python实现,希望你可以看看这个以及Javascript Neo4j驱动程序文档来转换它。
MATCH ( from:Person { id: '%s' } )
MATCH ( to:Person { id: '%s' } )
CREATE (from)-:KNOWS->(to)
答案 1 :(得分:0)
我认为值得报道我的经验。
我已经按照@sjc建议并尝试使用UNWIND。但是,这并不是那么简单,因为Cypher不允许您参数化节点标签或关系类型(我有十几种标签和关系类型)。但最终,我能够遍历所有可能的类型并向每个UNWIND块发送足够的项目(大约1000个)。
在我看来,使用UNWIND的代码速度要快得多,但还不够快(在一台体面的PC上应该没问题,并且有几百万个节点,对数亿个节点不太好,或者更多)。
插入器组件要快得多(上传1-2百万个节点几秒钟),虽然它需要降低HTTP访问权限并且我对Lucene 5.4的依赖性存在很多问题,因为我需要在使用Lucene 6的应用程序(生成数据)中使用,当我尝试在类路径中简单地用5.4交换5.4时发生了可怕的事情。我在那个there is some mechanism to make this possible附近,但它看起来并不容易,当然也没有那么好记录。
我绝对不会期望所有这些麻烦都能有效地执行这样的基本操作。