0
votes

If I have a graph by executing this query, then i want to delete a middle node say 'and' and connect its previous node say 'graph' to its child node say 'db' by using its corresponding outgoing relationships based on same 'seqid'

MERGE (n:Person { name:  'graph'}) 

MERGE (n:Person { name:  'and'}) 

MERGE (n:Person { name:  'relational'  })

MERGE (n:Person { name: 'nosql'})

MERGE (n:Person { name:  'server'})

MERGE (n:Person { name:  'db'})

MERGE (a:Person { name:  'graph'}) MERGE (b:Person { name:  'and' }) MERGE (a)-[:NEXT{seqid:1}]->(b)

MERGE (a:Person { name:  'and' }) MERGE (b:Person { name:  'db'}) MERGE (a)-[:NEXT{seqid:1 , caps: 'true'}]->(b)

MERGE (a:Person { name:  'relational'}) MERGE (b:Person { name:  'db'}) MERGE (a)-[:NEXT{seqid:1}]->(b)

MERGE (a:Person { name:  'nosql'}) MERGE (b:Person { name:  'db' }) MERGE (a)-[:NEXT{seqid:2, caps: 'true'}]->(b)

MERGE (a:Person { name:  'server'}) MERGE (b:Person { name:  'and' }) MERGE (a)-[:NEXT{seqid:1}]->(b)

MERGE (a:Person { name:  'and' }) MERGE (b:Person { name:  'db'}) MERGE (a)-[:NEXT{seqid:1}]->(b)

MERGE (a:Person { name:  'server'}) MERGE (b:Person { name:  'and'}) MERGE (a)-[:CONNECTS{seqid:2}]->(b)

MERGE (a:Person { name:  'and' }) MERGE (b:Person { name:  'db'}) MERGE (a)-[:CONNECTS{seqid:2, caps: 'true'}]->(b)

i.e.

(graph)-[:NEXT{seqid:1 , caps: 'true'}]->(db)

(relational)-[:NEXT{seqid:1}]->(db)

(nosql)-[:NEXT{seqid:2, caps: 'true'}]->(db)

(server)-[:NEXT{seqid:1}]->(db)

(server)-[:CONNECTS{seqid:2, caps: 'true'}]->(db)

pls help me to solve this.............

(I am using neo4j 2.3.6 community edition via java api in embedded mode..)

2

2 Answers

0
votes

The obstacle here is that relationship types cannot be created dynamically. You cannot check for the incoming relationships, not knowing their type, and create a new relationship of that same type.

If you know the types of the relationships you need to process, and can address those explicitly, then you can do this with Cypher. Here's the query to do this for all :NEXT relationships, copying over the properties of the relationship from the middle node to the end node over to the newly created relationship:

MATCH (middle:Person{name:'and'})
WITH middle
MATCH (from:Person)-[rFrom:NEXT]->(middle)
WHERE exists(rFrom.seqid)
WITH middle, rFrom, from
MATCH (middle)-[rTo:NEXT]->(to:Person)
WHERE rTo.seqid = rFrom.seqid
WITH middle, rFrom, from, rTo, to
CREATE (from)-[rNew:NEXT]->(to)
SET rNew += rTo
DELETE rFrom

You'll want to repeat this for every relationship type you're interested in, and when there are no more relationships to or from your middle node, delete the node.

Note that if you do upgrade to neo4j 3, the APOC Procedures library has procedures for graph refactoring, which will easily take care of this.

EDIT

Altered my Cypher above to do CREATE instead of MERGE.

Also removed deletion of the relationships from the middle node to the next node, as you seem want to take the relationship properties from the relationship connecting the middle node to the next node, and since there may be multiple incoming relationships to the middle node with the same type and id, but only a single relationship from the middle node with that type and id.

This means your ratio of incoming relationships with the same type and id is not equal to the outgoing relationships of the same type and id, so we'll be reusing those outgoing relationships when creating the new relationships.

Only after you're all done creating the new relationships should you detach and delete the middle node.

0
votes

Adding another answer that will fulfill all requirements, but requires Neo4j 3.0.x or greater. Specifically, this requires the apoc.create.relationship() procedure from APOC Procedures, which will let us create a relationship with a dynamic type, supplied from the matched from relationships.

This will take care of all relationships at once (at least those with seqid), so we should be okay to detach and delete the middle node at the end.

MATCH (middle:Person{name:'and'})
WITH middle
MATCH (from:Person)-[rFrom]->(middle)
WHERE EXISTS(rFrom.seqid)
WITH middle, rFrom, from
MATCH (middle)-[rTo]->(to:Person)
WHERE TYPE(rTo) = TYPE(rFrom) AND rTo.seqid = rFrom.seqid
WITH middle, rFrom, from, rTo, to
CALL apoc.create.relationship(from, TYPE(rFrom), PROPERTIES(rTo), to) YIELD rel
DETACH DELETE middle