Neo4j CSV导入:导入期间删除/过滤特定值

时间:2015-10-01 15:22:18

标签: neo4j cypher

我使用py2neo通过CSV上传导入数据。以下脚本读取每个列及其文件行并推送到Neo4j。文件包含四列下的数千行。有些列包括" n / a"," undefined"," null"," unknown"和空白细胞。当脚本迭代列和行时,它会将所有数据也推送到数据库。

我希望,当脚本读取" n / a"或" undefined"," null" ...它应该忽略这些数据并且不会推送数据库。

result_data = "./Excel2CSV/result.csv"
graph.cypher.execute("CREATE CONSTRAINT ON (result:RESULT) ASSERT result.id IS UNIQUE")
with open(result_data, 'r+') as in_file:
    reader = csv.reader(in_file, delimiter=';')
    next(reader, None)
    batch = graph.cypher.begin()
    try:
        i = 0;
        j = 0;
        for row in reader:
            if row:
                f_name = strip(row[0])
                l_name = strip(row[1])
                nickname = strip(row[2]
                text = strip(row[3])
                result = strip(row[4])
                query = """
                    merge (person:Person {f_name:{a}, l_name{b}, nickname{c}})
                    merge (text:TEXT {value:{d}})
                    merge (Result:RESULT {value:{e}})
                    merge (person)-[:WROTE]->(text)
                    merge (person)-[:REPLIED]->(result)
                """
                batch.append(query, {"a": f_name, "b": l_name, "c": nickname, "d": text, "e": result})
                i += 1
                j += 1
            batch.process()

关于以下答案的编辑:

例如,我正在创建一个名为" person"此节点有3个属性" f_name"来自{a}列," l_name"来自{b}列和"昵称"来自{c}专栏。假设每列都具有上述"不需要的"值。我使用第一个" f_name"创建了节点。属性:

WITH CASE WHEN {a} IN ["n/a", "undefined", "null"] THEN "" ELSE {a} END AS x
OPTIONAL MATCH (person:Person { f_name: x })

并且在传递给

之前

WITH CASE WHEN text IS NULL THEN [x] ELSE [] END AS todo FOREACH (i IN todo | CREATE (person:Person { l_name: i })),

我需要应用相同的过滤来删除" l_name"和#34;昵称"属性。而且我认为我应该定义新属性以将新属性附加到" person"节点

1 个答案:

答案 0 :(得分:1)

您可以修复上一个查询,以使其“正常”。但是,该方法仍然存在缺陷,因为数据库最终可能会有多个:TEXT节点没有属性。这是因为具有“bad”属性的每个MERGE将无法匹配现有节点并使用该属性创建新的新节点,然后删除该属性(因为您将其值设置为null) - 可能不是你想要的。

所以,我建议你选择一个非空值(例如,“”,甚至是字符串“null”)来设置值,如果传入的{c}有一个“坏”值。

匹配具有单个属性的节点

使用上述提议,如果节点只有一个属性,则以下简单查询应该有效(用“”替换“坏”值):

WITH CASE WHEN {c} IN ["n/a", "undefined", "null"] THEN "" ELSE {c} END AS x
MERGE (text:TEXT { value: x });

这不仅符合您的意图,而且效率更高,因为它不需要额外的WHERE OR SET条款。

匹配可能具有“额外”属性的节点

由于MERGE子句(指定任何属性)仅匹配完成属性集与子句匹配的节点,因此如果要查找的话,上述单属性解决方案将不起作用匹配即使节点具有MERGE子句中未指定的其他属性。

如果应该允许“额外”属性,这是一个应该有效的查询。

WITH CASE WHEN {c} IN ["n/a", "undefined", "null"] THEN "" ELSE {c} END AS x
OPTIONAL MATCH (text:TEXT { value: x })
WITH CASE WHEN text IS NULL THEN [x] ELSE [] END AS todo
FOREACH (i IN todo | CREATE (text:TEXT { value: i }));

OPTIONAL MATCH不像MERGE那样挑剔,即使有“额外”属性也会成功。如果OPTIONAL MATCH失败,则会将null分配给其节点和关系标识符。如果它迭代的集合是空的,FOREACH什么都不做。