cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Double relations when creating dynimic relations with apoc.merge.relationship

With a JSON structure like the following example:

{
	"JsonExport": [
		{
			"entities": [
				{
					"identity": "ENTITY_001",
					"surname": "SMIT",
					"entityLocationRelation": [
						{
							"parentIdentification": "PARENT_ENTITY_001",
							"typeRelation": "MEETING_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"
						},
						{
							"parentIdentification": "PARENT_ENTITY_001",
							"typeRelation": "FAMILY",
							"childIdentification": "ENTITY_003"
						}
					],
					"entityItemRelation": [
						{
							"parentIdentification": "PARENT_ENTITY_001",
							"typeRelation": "USER",
							"childIdentification": "ITEM_01"
						},
						{
							"parentIdentification": "PARENT_ENTITY_001",
							"typeRelation": "OWNER",
							"childIdentification": "ITEM_02"
						}
					]
				},
				{
					"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"
				}
			],
			"items": [
				{
					"type": "PHONE",
					"identity": "ITEM_01"
				},
				{
					"type": "LAPTOP",
					"identity": "ITEM_02"
				}
			]
		}
	]
}

Nodes and edges are created with the following:

WITH "file:///example3.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data

CALL apoc.merge.node(['Registration'], {id:data.identification}, {id:data.identification},{}) YIELD node AS vReg

UNWIND data.entities AS ent
	CALL apoc.merge.node(['Entity'], {id:ent.identity}, {},{}) YIELD node AS vEnt1
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON", {},{}, vEnt1) YIELD rel AS eReg1
		
		UNWIND ent.entityEntityRelation AS entEntR
			CALL apoc.merge.node(['Entity'],{id:entEntR.childIdentification},{},{id:entEntR.childIdentification}) YIELD node AS vEnt2
			CALL apoc.merge.relationship(vEnt1, entEntR.typeRelation, {},{},vEnt2) YIELD rel AS eEnt

UNWIND data.locations AS loc
	CALL apoc.merge.node(['Location'], {id:loc.identity}, {}) YIELD node AS vLoc
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vLoc) YIELD rel AS eReg2
	
		UNWIND ent.entityLocationRelation AS entLocR
			CALL apoc.merge.relationship(vEnt1, entLocR.typeRelation, {},{},vLoc) YIELD rel AS eLoc

UNWIND data.items AS item
	CALL apoc.merge.node(['Item'], {id:item.identity}, {}) YIELD node AS vItem
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vItem) YIELD rel AS eReg3
	
		UNWIND ent.entityItemRelation AS entItemR
			CALL apoc.merge.relationship(vEnt1, entItemR.typeRelation, {},{},vItem) YIELD rel AS eItem

RETURN vReg

There is one problem: double relations arise between "Entity" -> "Location" & "Item", as opposed to the created relations between the entities (see image). Or rather, relationships are created that do not exist. For example: ENTITY_01 has two relations to LOCATION_01, this should be only one: ENTITY_01-[:MEETING_AT]->LOCATION_01. What causes this problem and how can I solve it?

1 ACCEPTED SOLUTION

For reference purposes

WITH "file:///example3.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data

CALL apoc.merge.node(['Registration'], {id:data.identification}, {id:data.identification},{}) YIELD node AS vReg

UNWIND data.entities AS ent
	CALL apoc.merge.node(['Entity'], {id:ent.identity}, {},{}) YIELD node AS vEnt1
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON", {},{}, vEnt1) YIELD rel AS eReg1
		
		UNWIND ent.entityEntityRelation AS entEntR
			CALL apoc.merge.node(['Entity'],{id:entEntR.childIdentification},{},{id:entEntR.childIdentification}) YIELD node AS vEnt2
			CALL apoc.merge.relationship(vEnt1, entEntR.typeRelation, {},{},vEnt2) YIELD rel AS eEnt

UNWIND data.locations AS loc
	CALL apoc.merge.node(['Location'], {id:loc.identity}, {}) YIELD node AS vLoc
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vLoc) YIELD rel AS eReg2
	
		UNWIND ent.entityLocationRelation AS entLocR
			CALL apoc.merge.node(['Location'],{id:entLocR.locationIdentity},{},{id:entLocR.locationIdentity}) YIELD node AS vLoc2
			CALL apoc.merge.relationship(vEnt1, entLocR.typeRelation, {},{},vLoc2) YIELD rel AS eLoc

UNWIND data.items AS item
	CALL apoc.merge.node(['Item'], {id:item.identity}, {}) YIELD node AS vItem
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vItem) YIELD rel AS eReg3
	
		UNWIND ent.entityItemRelation AS entItemR
			CALL apoc.merge.node(['Item'],{id:entItemR.childIdentification},{},{id:entItemR.childIdentification}) YIELD node AS vItem2
			CALL apoc.merge.relationship(vEnt1, entItemR.typeRelation, {},{},vItem2) YIELD rel AS eItem

RETURN vReg

Like vEnt2, vLoc2 and vItem2 are also needed for it to work. Don't know if this is the most eloquent way to solve the problem but it works. Performance may be poor?

View solution in original post

1 REPLY 1

For reference purposes

WITH "file:///example3.json" AS json_file
CALL apoc.load.json(json_file,"$.JsonExport.*" ) YIELD value AS data

CALL apoc.merge.node(['Registration'], {id:data.identification}, {id:data.identification},{}) YIELD node AS vReg

UNWIND data.entities AS ent
	CALL apoc.merge.node(['Entity'], {id:ent.identity}, {},{}) YIELD node AS vEnt1
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON", {},{}, vEnt1) YIELD rel AS eReg1
		
		UNWIND ent.entityEntityRelation AS entEntR
			CALL apoc.merge.node(['Entity'],{id:entEntR.childIdentification},{},{id:entEntR.childIdentification}) YIELD node AS vEnt2
			CALL apoc.merge.relationship(vEnt1, entEntR.typeRelation, {},{},vEnt2) YIELD rel AS eEnt

UNWIND data.locations AS loc
	CALL apoc.merge.node(['Location'], {id:loc.identity}, {}) YIELD node AS vLoc
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vLoc) YIELD rel AS eReg2
	
		UNWIND ent.entityLocationRelation AS entLocR
			CALL apoc.merge.node(['Location'],{id:entLocR.locationIdentity},{},{id:entLocR.locationIdentity}) YIELD node AS vLoc2
			CALL apoc.merge.relationship(vEnt1, entLocR.typeRelation, {},{},vLoc2) YIELD rel AS eLoc

UNWIND data.items AS item
	CALL apoc.merge.node(['Item'], {id:item.identity}, {}) YIELD node AS vItem
	CALL apoc.merge.relationship(vReg, "REGISTERED_ON",{}, {},vItem) YIELD rel AS eReg3
	
		UNWIND ent.entityItemRelation AS entItemR
			CALL apoc.merge.node(['Item'],{id:entItemR.childIdentification},{},{id:entItemR.childIdentification}) YIELD node AS vItem2
			CALL apoc.merge.relationship(vEnt1, entItemR.typeRelation, {},{},vItem2) YIELD rel AS eItem

RETURN vReg

Like vEnt2, vLoc2 and vItem2 are also needed for it to work. Don't know if this is the most eloquent way to solve the problem but it works. Performance may be poor?