Neo4j从CSV文件更新节点

时间:2016-12-22 17:57:08

标签: neo4j cypher

我需要使用新数据更新现有节点,如果节点不存在,则需要创建一个新节点。我试图用以下查询来做到这一点:

# 'k' is the key for the dictionary i.e: "Cake"
# and 'v' is the value for that key i.e: "["Flour", "Eggs", "Milk"]"
for k, v in my_recipes.items():
    # checks to see if all items in values 
    # are in the ingredients list
    if all(i in ingredients for i in v):
        # if they are, print out what can be made
        print("Can make {}".format(k))

查询运行了很长时间但数据库大小没有增加。

我在这里做错了吗?还有另一种更新节点的方法吗?

1 个答案:

答案 0 :(得分:1)

MERGE clause就是这样做的。来自文档:

  

MERGE可以匹配现有节点并绑定它们,也可以创建新数据并绑定它们。它就像是MATCH和CREATE的组合,它还允许您指定在匹配或创建数据时会发生什么。

让我们来看看你的查询。这一行:

MERGE (c:Company {companyNumber:line1.companyNumber})

如果没有标签Company的现有节点具有属性Company,其值为companyNumber,则

生成标签为line1.companyNumber的新节点对于CSV文件中的此行。这类似于关系数据库中的主键。 companyNumber是唯一标识Company节点的东西,您不希望为此属性创建具有相同值的重复节点。

您应also create a uniqueness constraint在数据库架构级别强制执行此操作:

CREATE CONSTRAINT ON (c:Company) ASSERT c.companyNumber IS UNIQUE;

但是否则第一部分看起来不错。

现在是您查询的下一部分:

MERGE (ca:CompanyAddress)
ON CREATE SET ca.county=line1.County
ON MATCH SET ca.county=line1.County
ON CREATE SET ca.country=line1.Country
ON MATCH SET ca.country=line1.Country
ON CREATE SET ca.postCode=line1.postCode 
ON MATCH SET ca.postCode=line1.postCode
ON CREATE SET ca.poBox=line1.POBox
ON MATCH SET ca.poBox=line1.POBox
ON CREATE SET ca.careOf=line1.CareOf
ON MATCH SET ca.careOf=line1.CareOf
ON CREATE SET ca.addressLine1=line1.AddressLine1
ON MATCH SET ca.addressLine1=line1.AddressLine1
ON CREATE SET ca.addressLine2=line1.AddressLine2
ON MATCH SET ca.addressLine2=line1.AddressLine2

MERGE采用一种模式,然后搜索图表以查看此模式是否存在,如果数据不存在则创建数据。您指定给MERGE的模式是标签为CompanyAddress的节点。这将MATCH所有节点上标记为CompanyAddress,无论其属性如何。然后,以下SET语句将更新所有 CompanyAddress个节点的属性。因此,您最终会得到的结果是,查询的这一部分最多只能创建一个CompanyAddress节点,并且所有现有的CompanyAddress节点将具有相同的属性值,无论CSV文件中的最后一行是什么

相反,你应MERGE使用多个属性:

MERGE (ca:CompanyAddress {
    county: line1.County, 
    country: line1.Country,
    poBox: line1.POBox,
    careof: line1.Careof,
    addressLine1: line1.AddressLine1,
    addressLine2: line1.AddressLine2
})
MERGE (c)-[:HAS_COMPANY_ADDRESS]->(ca)

虽然请注意,如果一个字段更改,此方法将为CompanyAddress创建一个新节点。如果您想更改地址更改时的字段,则需要为该地址引入一些唯一ID,并在该属性上引用MERGE

<强>更新

鉴于数据建模约束,每个Company节点仅连接到一个CompanyAddress节点,此查询:

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM
'file:///C:/Users/Zona5/Documents/Neo4j/check/import/cd1_5.csv' AS line1
MERGE (c:Company {companyNumber:line1.companyNumber})
MERGE (c)-[:HAS_COMPANY_ADDRESS]->(ca:CompanyAddress)
SET ca.county=line1.County,
    ca.country=line1.Country,
    ca.postCode=line1.postCode,
    ca.poBox=line1.POBox,
    ca.careOf=line1.CareOf,
    ca.addressLine1=line1.AddressLine1,
    ca.addressLine2=line1.AddressLine2

将创建CompanyCompanyAddressHAS_COMPANY_ADDRESS关系的节点(如果它们不存在),然后更新CompanyAddress的属性。