在庞大的数据集上创建关系时出错

时间:2016-08-23 17:11:57

标签: neo4j cypher

我的问题类似于此处指出的问题:

Creating unique node and relationship NEO4J over huge dataset

我有2个表实体(Entities.txt)& 关系(EntitiesRelationships_Updated.txt)如下所示:这两个表都位于Neo4j数据库中的导入文件夹中。我想要做的是使用load csv命令加载表,然后创建关系。

如下表所示:如果ParentID为0,则表示ENT_ID没有父级。如果已填充,则它具有父级。例如,在下表中,ENT_ID = 3是ENT_ID = 4的父级,ENT_ID = 1是ENT_ID = 2的父级

**Entity Table**
ENT_ID  Name  PARENTID
1      ABC     0     
2      DEF     1
3      GHI     0
4      JKG     3



**Relationship Table**
RID ENT_IDPARENT ENT_IDCHILD 
 1     1        2
 2     3        5

实体表有200万条记录,关系表有大约400K行

每个RID都有一个与之关联的特定标记。例如,RID = 1表示关系是 A FATHER_OF B ; RID = 2使得关系为 A MOTHER_OF B 。类似地,有20个这样的RID相关联。

这两种都是txt格式。

我的第一步是加载实体表。我使用了以下脚本:

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///Entities.txt" AS Entity FIELDTERMINATOR '|'
CREATE (n:Entity{ENT_ID: toInt(Entity.ENT_ID),NAME: Entity.NAME,PARENTID: toInt(Entity.PARENTID)})

此查询正常。加载2.8mil记录大约需要10分钟。我要做的下一步是索引记录:

CREATE INDEX ON :Entity(PARENTID)
CREATE INDEX ON :Entity(ENT_ID)

此查询也运行正常。在此之后,我尝试使用与上面链接中类似的查询从关系表创建关系:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:///EntitiesRelationships_Updated.txt" AS Rships FIELDTERMINATOR '|' 
MATCH (n:A {ENT_IDPARENT : Rships.ENT_IDPARENT})
with Entity, n
MATCH (m:B {ENT_IDCHILD : Rships.ENT_IDCHILD})
with m,n
MERGE (n)-[r:RELATION_OF]->(m);

当我这样做时,我的查询会持续运行大约一个小时并停在特定大小(在我的情况下为2.2gb)我根据上面的链接进行了此查询。这包括从下面的解决方案编辑,但仍然无法正常工作

我还有一个查询,如下所示(基于上面的链接)。我运行此查询,因为我想创建一个基于实体表的关系

PROFILE
MATCH(Entity)
MATCH (a:Entity {ENT_ID : Entity.ENT_ID})
WITH Entity, a
MATCH (b:Entity {PARENTID : Entity.PARENTID})
WITH a,b
MERGE (a)-[r:PARENT_OF]->(b)

当我尝试运行此查询时,我收到了Java堆空间错误。不幸的是,我无法获得这些解决方案。

如果我做错了什么,请你指点一下吗?

2 个答案:

答案 0 :(得分:1)

此查询允许您利用Sub TextFile_FindReplace() Dim TextFile As Integer Dim FilePath As String Dim FileContent As String FilePath = Application.ActiveWorkbook.Path & "\NEWTEST.txt" TextFile = FreeFile Open FilePath For Input As TextFile FileContent = Input(LOF(TextFile), TextFile) FileContent = Replace(FileContent, "FOO", "BAR") Print #TextFile, FileContent Close TextFile End Sub 索引:

:Entity(ENT_ID)

当属性值来自另一个节点时,Cypher不使用索引。为了解决这个问题,上面的查询使用MATCH (child:Entity) WHERE child.PARENTID > 0 WITH child.PARENTID AS pid, child MATCH (parent:Entity {ENT_ID : pid}) MERGE (parent)-[:PARENT_OF]->(child); 子句将WITH表示为变量(child.PARENTID)。此查询的时间复杂度应为O(N)。原始查询的复杂度为O(N * N)。

[EDITED]

如果上述查询花费的时间过长或遇到可能与内存不足相关的错误,请尝试使用此变体,该变体一次创建1000个新关系。您可以将pid更改为任何适用于您的号码。

1000

MATCH (child:Entity) WHERE child.PARENTID > 0 AND NOT ()-[:PARENT_OF]->(child) WITH child.PARENTID AS pid, child LIMIT 1000 MATCH (parent:Entity {ENT_ID : pid}) CREATE (parent)-[:PARENT_OF]->(child) RETURN COUNT(*); 子句筛选出已有父关系的WHERE个节点。并且child操作已更改为更简单的MERGE操作,因为我们已经确定该关系尚不存在。查询返回创建的关系数的计数。如果结果小于CREATE,则表示已创建所有父关系。

最后,为了使重复的查询自动化,您可以在neo4j服务器上安装APOC插件并使用1000过程,该过程将重复调用查询,直到它返回0.在此示例中,我使用10000的apoc.periodic.commit参数:

limit

答案 1 :(得分:0)

您的实体创建Cypher看起来很好,您的索引也是如此。

我对最后两个Cypher片段感到困惑。

由于您的关系具有与之关联的特定标签或ID,因此最好通过从关系表数据加载来添加您的关系,尽管查询中的节点标签(A和B)不是&#39 ; t在您的实体创建中使用,并且不在图表中,也不是ENT_IDPARENT或ENT_IDCHILD字段。看起来这不是你所使用的Cypher,而是你建立的一个例子吗?

我将此关系创建查询更改为此,稍后设置关系的type属性以进行后处理(这假设在相同的两个节点之间只能存在一个:RELATION_OF关系):

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:///EntitiesRelationships_Updated.txt" AS Rships FIELDTERMINATOR '|' 
MATCH (parent:Entity {ENT_ID : Rships.ENT_IDPARENT})
MATCH (child:Entity {ENT_ID : Rships.ENT_IDCHILD})
MERGE (parent)-[r:RELATION_OF]->(child)
ON CREATE SET r.RID = Rships.RID;

稍后,如果您愿意,可以匹配与RID的关系,并添加相应的类型(" FATHER_OF"," MOTHER_OF"等)属性。

至于创建:PARENT_OF关系,你在一个绑定到图中每个节点的Entity变量上做一些额外的匹配 - 摆脱它。

相反,请使用:

PROFILE
// first, match on all Entities with a PARENTID property
MATCH(child:Entity)
WHERE EXISTS(child.PARENTID)
// next, find the parent for each child by the child's PARENTID
WITH child
MATCH (parent:Entity {ENT_ID : child.PARENTID})
MERGE (parent)-[:PARENT_OF]->(child)
// lastly remove the parentid from the child, so it won't be reprocessed
// if we run the query again.
REMOVE child.PARENTID

编辑上述查询以对child.PARENTID使用存在性检查,并在创建相应关系后删除child.PARENTID。

如果您需要使用批处理的解决方案,可以手动执行此操作(将LIMIT 100000添加到WITH child行,也可以安装APOC Procedures Library并使用其periodic.commit() function批处理你的处理。