从CSV加载数据模式的问题

时间:2015-03-01 10:53:20

标签: neo4j cypher

我尝试使用cypher命令行从cvs文件中将数据模式加载到neo4j中。我有两个数据文件,一个包含对象,另一个包含对象部分。

目标文件:

ID
ABC-DE
DEF

部分档案:

ID  ParentID    Level   Size
ABC ABC-DE  1   3
DE  ABC-DE  1   2
AB  ABC 2   2
BC  ABC 2   2
DE  DEF 1   2
F   DEF 2   1
A   AB  3   1
B   AB  3   1
B   BC  3   1
C   BC  3   1
D   DE  3   1
E   DE  3   1

用于加载数据的Cypher命令行:

LOAD CSV WITH HEADERS FROM 'file:///path_to_file/object.csv' as csvLine FIELDTERMINATOR '\t' CREATE (:Object { Name: csvLine.ID})  RETURN count(*);
LOAD CSV WITH HEADERS FROM 'file:///path_to_file/part.csv' as csvLine FIELDTERMINATOR '\t' MATCH (o:Object {Name: csvLine.ParentID}) MERGE (p:Part {Name: csvLine.ID}) ON CREATE SET p.Size = csvLine.Size CREATE (o) -[:hasPart {Level: csvLine.Level}]-> (p) RETURN count(*);
LOAD CSV WITH HEADERS FROM 'file:///path_to_file/part.csv' as csvLine FIELDTERMINATOR '\t' MATCH (o:Part {Name: csvLine.ParentID}) MERGE (p:Part {Name: csvLine.ID}) ON CREATE SET p.Size = csvLine.Size CREATE (o) -[:hasPart {Level: csvLine.Level}]-> (p) return count(*);

前两个命令行正确执行,分别创建2个和3个节点以及相应的链接。第三个命令行只创建4个节点:AB,BC,D和E.显然,只创建和链接链接到现有节点的节点。

从CSV文件内容中,我们可以看到父节点在子节点之前列出,因此我们可以预期节点A,B和C可以创建并相应地链接到AB和BC。

CSV的当前行为是否加载了预期的行为,这会阻止加载此类模式,或者我的代码或错误中是否存在问题?

neo4j 2.1.7和neo4j 2.2.0-M04都存在此问题。

1 个答案:

答案 0 :(得分:1)

所以我认为你的问题是cypher将许多更新批量编译到一个事务中,然后提交它们。它投入交易的数量是configurable with USING PERIODIC COMMIT。我可能是错的,但我认为通常它会把整个数据加载视为一个大事务。

对于你来说,这是有问题的,因为当你进入第6行时,你可能需要引用一个本来应该在第3行创建的节点。除了不工作;如果事务尚未提交,因为cypher正在对一堆结果进行批处理)那么尚未提交的结果可能无法用于后续运行的查询。

所以你有几个选择;一个是在该部分文件上进行两次导入IMPORT。在你第一次通过时你可以这样做:

LOAD CSV WITH HEADERS FROM 'file:///path_to_file/part.csv' as csvLine FIELDTERMINATOR '\t' 
MERGE (p:Part {Name: csvLine.ID}) ON CREATE SET p.Size = csvLine.Size CREATE (o) -[:hasPart {Level: csvLine.Level}]-> (p) return count(*);

(第一个将确保DB中存在所有部分)

然后在第二遍你可能会这样做:

LOAD CSV WITH HEADERS FROM 'file:///path_to_file/part.csv' as csvLine FIELDTERMINATOR '\t' MATCH (o:Part {Name: csvLine.ParentID}) MATCH (p:Part {Name: csvLine.ID}) CREATE (o) -[:hasPart {Level: csvLine.Level}]-> (p) return count(*);

(这只会将它们与人际关系联系起来)

另一种选择是做USING PERIODIC COMMIT 1之类的事情,但我认为这不是一个好主意;存在交易开销,如果您有相当数量的数据,这将大大减慢您的数据负载。

编辑如果我是你,我会进行双程导入。此外,一般来说,依靠像这样的平面文件中的记录排序并不是一个好主意,它们往往是凌乱的。最后,如果您对零件文件进行双程导入,请注意您根本不需要您的目标文件!任何涉及的对象都将通过零件文件创建,并且对象文件不会添加任何额外的属性而不是部件引用。