在我的模型中,我有两种类型的节点:系统和数据集。每个数据集都属于一个系统。这由CONTAINS_DATASET关系表示。
作为一般规则;数据集名称在给定系统中必须唯一。如果数据集包含在不同的系统中,则允许重复的数据集名称。
我正在尝试通过Cypher强制执行;当有人尝试创建一个包含在系统中的数据集时;如果数据集的名称与该系统的CONTAINED_IN中的现有数据集不匹配,则Cypher只会创建一个新的数据集。
我想我需要一个MERGE语句,其中包含基于与系统的关系的过滤条件,但是我不知道该怎么做。我已经在下面包含了我正在使用的代码,但是它只是一个合并,不考虑数据集所驻留的系统。
:params
"data": {
"System": [
{
"name": "System 1",
"datasets": [
{
"name": "Customers"
}
]
},
{
"name": "System 2",
"datasets": [
{
"name": "Customers"
}
]
},
{
"name": "System 3",
"datasets": [
{
"name": "Products"
}
]
}
]
}
UNWIND {data} as data
UNWIND data.System as systems
UNWIND systems.datasets as datasets
MERGE (sy:System { name: systems.name})
ON CREATE SET sy.status='New'
ON MATCH SET sy.status='Updated'
MERGE (da:Dataset { name: datasets.name})
MERGE (sy)-[:CONTAINS_DATASET]->(dan:Dataset { name: datasets.name })
return *
上面的查询还创建了两个我没想到的其他节点,因此对此的任何帮助也将不胜感激:
答案 0 :(得分:2)
您在这里很近,您的Cypher实际上拥有您需要的解决方案:
MERGE (sy)-[:CONTAINS_DATASET]->(dan:Dataset { name: datasets.name })
此模式具有一个绑定变量(先前与图形元素匹配)sy
,以及一个未绑定变量(先前不与任何元素匹配,在查询中首次出现)变量dan
。
MERGE就像对模式进行匹配,然后行为将根据该模式是否存在于图形中而改变。
如果它存在于图中(sy
与具有给定名称的:Dataset节点具有:CONTAINS_DATASET关系),则它将重用现有的图结构,并且dan
将绑定到该图结构现有的连接节点。
如果图形中不存在该模式,则将创建整个模式,这将包括创建任何未绑定的节点,例如dan
。如果该模式不存在,它将锁定该模式(sy
)的绑定部分,进行仔细检查以确保在检查时间和锁定时间之间没有任何更改,然后它将创建模式中先前未绑定的部分。 sy
是先前绑定的,因此它将使用同一节点而不是创建一个新节点。 (dan:Dataset { name: datasets.name })
之前未绑定,因此将创建具有此标签和此属性的新节点,并通过:CONTAINS_DATASET关系将其连接到sy
。
因此,此行为应完全满足您的需要,重复使用具有该名称的已连接节点(如果存在),或创建一个具有该名称的全新节点并按sy
节点进行连接。
对于您看到的重复项,这是因为该行之前的行:
MERGE (da:Dataset { name: datasets.name})
这不是必需的,您已经可以在其后的一行中满足您的需求,因此请将其删除,您的查询应该会为您服务。
有关our knowledge base article中MERGE行为的更多详细信息。