我的问题类似于此处指出的问题:
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堆空间错误。不幸的是,我无法获得这些解决方案。
如果我做错了什么,请你指点一下吗?
答案 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批处理你的处理。