从JSON创建节点和关系(动态)
我在一个类似以下示例的结构中有几百个JSON:从JSON创建节点和关系(动态),json,neo4j,cypher,Json,Neo4j,Cypher,我在一个类似以下示例的结构中有几百个JSON: { "JsonExport": [ { "entities": [ { "identity": "ENTITY_001", "surname": "SMIT", "entityL
{
"JsonExport": [
{
"entities": [
{
"identity": "ENTITY_001",
"surname": "SMIT",
"entityLocationRelation": [
{
"parentIdentification": "PARENT_ENTITY_001",
"typeRelation": "SEEN_AT",
"locationIdentity": "LOCATION_001"
},
{
"parentIdentification": "PARENT_ENTITY_001",
"typeRelation": "SEEN_AT",
"locationIdentity": "LOCATION_002"
}
],
"entityEntityRelation": [
{
"parentIdentification": "PARENT_ENTITY_001",
"typeRelation": "FRIENDS_WITH",
"childIdentification": "ENTITY_002"
}
]
},
{
"identity": "ENTITY_002",
"surname": "JACKSON",
"entityLocationRelation": [
{
"parentIdentification": "PARENT_ENTITY_002",
"typeRelation": "SEEN_AT",
"locationIdentity": "LOCATION_001"
}
]
},
{
"identity": "ENTITY_003",
"surname": "JOHNSON"
}
],
"identification": "REGISTRATION_001",
"locations": [
{
"city": "LONDON",
"identity": "LOCATION_001"
},
{
"city": "PARIS",
"identity": "LOCATION_002"
}
]
}
]
}
有了这些JSON,我想制作一个由以下节点组成的图:注册、实体和位置。这一部分我已经弄明白了,并做了如下工作:
WITH "file:///example.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data
MERGE(r:Registration {id:data.identification})
WITH json_file
CALL apoc.load.json(json_file,"$.JsonExport..locations.*" ) YIELD value AS locations
MERGE(l:Locations{identity:locations.identity, name:locations.city})
WITH json_file
CALL apoc.load.json(json_file,"$.JsonExport..entities.*" ) YIELD value AS entities
MERGE(e:Entities {name:entities.surname, identity:entities.identity})
所有实体和地点都应与注册有关。我想我可以通过使用以下代码来做到这一点:
MERGE (e)-[:REGISTERED_ON]->(r)
MERGE (l)-[:REGISTERED_ON]->(r)
但是,此代码没有提供所需的输出。它会创建额外的“空”节点,并且不会连接到注册节点。因此,第一个问题是:如何将位置和实体节点连接到注册节点。根据其他JSON,实体和位置应该只链接到特定的注册
此外,我希望创建实体->位置关系和实体-实体关系,并使用给定类型的关系(SEEN_AT或FRIENDS_WITH)作为给定关系的标签。如何做到这一点?我在这一点上有点迷茫,不知道如何解决这个问题。如果有人能把我引向正确的方向,我将不胜感激
e
和r
)不存储在数据库中,仅绑定到单个查询中的值<对具有未绑定变量的模式进行代码>合并只会创建整个模式(包括为未绑定节点变量创建空节点)
进行设置
调用/合并
子句组都会执行多次(因为每个先前的调用
都会生成多行,并且行数会成倍增加)。您可以使用来绕过这一点,但在您的情况下,这是不必要的,因为您可以在一次通过JSON数据的过程中完成整个查询
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data
MERGE(r:Registration {id:data.identification})
FOREACH(ent IN data.entities |
MERGE (e:Entities {identity: ent.identity})
ON CREATE SET e.name = ent.surname
MERGE (e)-[:REGISTERED_ON]->(r)
FOREACH(loc1 IN ent.entityLocationRelation |
MERGE (l1:Locations {identity: loc1.locationIdentity})
MERGE (e)-[:SEEN_AT]->(l1))
FOREACH(ent2 IN ent.entityEntityRelation |
MERGE (e2:Entities {identity: ent2.childIdentification})
MERGE (e)-[:FRIENDS_WITH]->(e2))
)
FOREACH(loc IN data.locations |
MERGE (l:Locations{identity:loc.identity})
ON CREATE SET l.name = loc.city
MERGE (l)-[:REGISTERED_ON]->(r)
)
为简单起见,它使用和关系类型上的注册对朋友进行硬编码,因为合并只支持硬编码关系类型
e
和r
)不存储在数据库中,仅绑定到单个查询中的值<对具有未绑定变量的模式进行代码>合并只会创建整个模式(包括为未绑定节点变量创建空节点)
进行设置
调用/合并
子句组都会执行多次(因为每个先前的调用
都会生成多行,并且行数会成倍增加)。您可以使用来绕过这一点,但在您的情况下,这是不必要的,因为您可以在一次通过JSON数据的过程中完成整个查询
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data
MERGE(r:Registration {id:data.identification})
FOREACH(ent IN data.entities |
MERGE (e:Entities {identity: ent.identity})
ON CREATE SET e.name = ent.surname
MERGE (e)-[:REGISTERED_ON]->(r)
FOREACH(loc1 IN ent.entityLocationRelation |
MERGE (l1:Locations {identity: loc1.locationIdentity})
MERGE (e)-[:SEEN_AT]->(l1))
FOREACH(ent2 IN ent.entityEntityRelation |
MERGE (e2:Entities {identity: ent2.childIdentification})
MERGE (e)-[:FRIENDS_WITH]->(e2))
)
FOREACH(loc IN data.locations |
MERGE (l:Locations{identity:loc.identity})
ON CREATE SET l.name = loc.city
MERGE (l)-[:REGISTERED_ON]->(r)
)
为简单起见,它使用和关系类型上的注册对朋友进行硬编码,因为合并只支持硬编码的关系类型。所以玩neo4j/cyper我学到了一些新东西,并找到了解决问题的另一种方法。基于给定的示例数据,以下内容可以动态创建节点和边
WITH "file:///example.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data
CALL apoc.merge.node(['Registration'], {id:data.identification}, {},{}) YIELD node AS vReg
UNWIND data.entities AS ent
CALL apoc.merge.node(['Person'], {id:ent.identity}, {}, {id:ent.identity, surname:ent.surname}) YIELD node AS vPer1
UNWIND ent.entityEntityRelation AS entRel
CALL apoc.merge.node(['Person'],{id:entRel.childIdentification},{id:entRel.childIdentification},{}) YIELD node AS vPer2
CALL apoc.merge.relationship(vPer1, entRel.typeRelation, {},{},vPer2) YIELD rel AS ePer
UNWIND data.locations AS loc
CALL apoc.merge.node(['Location'], {id:loc.identity}, {name:loc.city}) YIELD node AS vLoc
UNWIND ent.entityLocationRelation AS locRel
CALL apoc.merge.relationship(vPer1, locRel.typeRelation, {},{},vLoc) YIELD rel AS eLoc
CALL apoc.merge.relationship(vLoc, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg1
CALL apoc.merge.relationship(vPer1, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg2
CALL apoc.merge.relationship(vPer2, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg3
RETURN vPer1,vPer2, vReg, vLoc, eLoc, eReg1, eReg2, eReg3
所以在玩neo4j/cyper时,我学到了一些新东西,并找到了解决问题的另一种方法。基于给定的示例数据,以下内容可以动态创建节点和边
WITH "file:///example.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data
CALL apoc.merge.node(['Registration'], {id:data.identification}, {},{}) YIELD node AS vReg
UNWIND data.entities AS ent
CALL apoc.merge.node(['Person'], {id:ent.identity}, {}, {id:ent.identity, surname:ent.surname}) YIELD node AS vPer1
UNWIND ent.entityEntityRelation AS entRel
CALL apoc.merge.node(['Person'],{id:entRel.childIdentification},{id:entRel.childIdentification},{}) YIELD node AS vPer2
CALL apoc.merge.relationship(vPer1, entRel.typeRelation, {},{},vPer2) YIELD rel AS ePer
UNWIND data.locations AS loc
CALL apoc.merge.node(['Location'], {id:loc.identity}, {name:loc.city}) YIELD node AS vLoc
UNWIND ent.entityLocationRelation AS locRel
CALL apoc.merge.relationship(vPer1, locRel.typeRelation, {},{},vLoc) YIELD rel AS eLoc
CALL apoc.merge.relationship(vLoc, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg1
CALL apoc.merge.relationship(vPer1, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg2
CALL apoc.merge.relationship(vPer2, "REGISTERED_ON", {},{},vReg) YIELD rel AS eReg3
RETURN vPer1,vPer2, vReg, vLoc, eLoc, eReg1, eReg2, eReg3
谢谢你的回答!答案似乎并不完全正确(
无法使用标识的null属性值合并节点)。可能与de JSON结构有关?但其背后的总体思路有些清晰。感谢您指出这一点,这有助于我继续前进!对于动态不动产,类似于apoc.create.relationship
的内容将是一个选项,对吗?我修复了MERGE
。现在应该可以工作了。很遗憾,您不能在FOREACH
中调用过程。谢谢您的回答!答案似乎并不完全正确(无法使用标识的null属性值合并节点)。可能与de JSON结构有关?但其背后的总体思路有些清晰。感谢您指出这一点,这有助于我继续前进!对于动态不动产,类似于apoc.create.relationship
的内容将是一个选项,对吗?我修复了MERGE
。现在应该可以工作了。不幸的是,您不能在FOREACH
中调用过程。