无法与空值进行合并;在neo4j中使用空属性值无法合并节点

14

我有一个csv文件中的一列,看起来像这样:

enter image description here

我正在使用此代码来测试日期分割的工作原理:

LOAD CSV WITH HEADERS FROM
'file:///..some_csv.csv' AS line
WITH
SPLIT(line.date_of_birth, '/') AS date_of_birth
return date_of_birth;

这段代码块运行良好并返回了我所期望的结果,即每个日期的三个值的集合,或者如果没有日期,则可能是null(例如:)。
[4, 5, 1971]  
[0, 0, 2003]  
[0, 0, 2005]  
 . . .  
null  
null  
 . . .  

我的问题是,这些创建的空值问题是什么,为什么在存在空值时我不能执行MERGE操作?

LOAD CSV WITH HEADERS FROM
'file:///..some_csv.csv' AS line
WITH
SPLIT(line.date_of_birth, '/') AS date_of_birth, line
MERGE (p:Person {
 date_of_birth: date_of_birth
});

上面的这个块给了我一个错误:

Cannot merge node using null property value for date_of_birth  

我搜索过,只发现一个关于该错误的SO问题,但没有答案。其他搜索也没有帮助。 我原本认为如果没有值,那么Neo4j就不会创建元素。我想也许不能生成节点,因为如果没有值生成节点怎么可能呢?所以,既然我知道没有丢失ID,也许我可以使用ID和日期进行MERGE,这样Neo4j总是能看到一个值。但是这段代码也没有更好(相同的错误消息)。
LOAD CSV WITH HEADERS FROM
'file:///..some_csv.csv' AS line
WITH
SPLIT(line.date_of_birth, '/') AS date_of_birth, line
MERGE (p:Person {
 ID: line.ID
,date_of_birth: date_of_birth
});  

我的下一个想法是,也许出现这个错误是因为我试图在斜杠上分割一个空值?也许整个问题都是由于“SPLIT”引起的。

但遗憾的是,当简化为以下内容时,仍然出现相同的错误:

LOAD CSV WITH HEADERS FROM
'file:///..some_csv.csv' AS line
WITH line
MERGE (p:Person {
 subject_person_id: line.subject_person_id
,date_of_birth: line.date_of_birth
});

我其实不太理解错误的原因。感谢您查看这个问题。

编辑

@stdob--和@cybersam都给出了同样出色的回答,如果您通过Google来到这里,请将他们都视为已被接受。


2
我尽管没有任何空值或空字符串,但仍然会收到此错误。 - pl80
2
已经理解了:当从CSV导入时,如果列名被包含在反引号(如由于空格)内并且存在外文字符,则会出现此错误。 - pl80
5个回答

17
正如 @cybersam 所说,MERGE 在属性在空范围内设置的查询中效果不佳。因此,您可以使用 ON CREATE and ON MATCH
LOAD CSV WITH HEADERS FROM
  'file:///..some_csv.csv' AS line
MERGE (p:Person {
  subject_person_id: line.subject_person_id
})
  ON CREATE SET p.date_of_birth = line.date_of_birth
  ON MATCH SET p.date_of_birth = line.date_of_birth

如果ON CREATEON MATCH执行完全相同的SET操作,则只需将这两个语句替换为单个SET - cybersam

13

有些Cypher查询(如MERGE)无法很好地处理NULL值。

在处理这种情况时,使用FOREACH子句来有条件地执行MERGE是一种比较棘手的解决方案。以下查询可能适用于您:

LOAD CSV WITH HEADERS FROM 'file:///..some_csv.csv' AS line
FOREACH (x IN CASE WHEN line.date_of_birth IS NULL THEN [] ELSE [1] END |
  MERGE (:Person {date_of_birth: SPLIT(line.date_of_birth, '/')})
);

[使用答案更新“简化”查询]

在你的MERGE子句中排除可能为null的属性。此外,MERGE子句必须精心制作,以避免通过限制在MERGE中指定的属性而创建不需要的额外节点。

LOAD CSV WITH HEADERS FROM 'file:///..some_csv.csv' AS line
MERGE (p:Person {subject_person_id: line.subject_person_id})
SET p.date_of_birth = line.date_of_birth

6

我比较喜欢的另一个解决方案是告诉Cypher跳过字段为空的行,方法如下:

USING PERIODIC COMMIT #
LOAD CSV WITH HEADERS FROM
'file:///.../csv.csv' AS line
WITH line, SPLIT(line.somedatefield, delimiter) AS date
WHERE NOT line.somedatefield IS NULL

[THE REST OF YOUR QUERY INVOLVING THE FIELD]

1
在我看来,这是非常优雅的解决方案。 - darefilz
“WHERE NOT” 对我很关键。 - canbax

5

您也可以使用COALESCE(n.property?, {defaultValue})

该函数与NVL类似,用于在查询语句中处理空值。如果n.property为空,则返回默认值{defaultValue}。


1
为什么在 property 后面有一个问号?这些 {} 是否意味着必填值,就像 Backus-Naur 符号表示法中的那样? - ekkis

0

按照Vojtech Ruzicka的方法,您可以使用以下代码:your_value:COALESCE(line.your_value, 'default value')

如果您需要更多信息,请单击此处here查看文档。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接