Shawn
Shawn

Reputation: 363

Cypher - Number ordered relationship

I am stumbling on a cypher query. I would like to create a relationship where there is an implicit order based on an integer property per instruction. For example, I would like to match address_1 to address_2 and address_2 to address_3, and so forth when the WHERE condition applies. Here is the statement attempted:

MATCH (i:Instruction), (i2:Instruction)
 WHERE i.address < i2.address AND i.vars_written = i2.vars_read
MERGE (i)-[r:USED_BY]->(i2)
RETURN i, i2, r

The issue is that a lower number address will map to all other addresses that fit the WHERE condition instead of just to the relevant ones - creating additional relationships where there shouldn't be, like address_1 to address_3.

One instruction may have multiple USED_BY relationships but once another instruction has the same vars_written property, it should start a new USED_BY relationship.

To provide a concrete example, consider the following 4 nodes:

Index 1 parameters: {
  address: 1
  vars_written: var_b
  vars_read: var_a
}

Index 2 parameters: {
  address: 2
  vars_written: var_c
  vars_read: var_b
}

Index 3 parameters: {
  address: 3
  vars_written: var_c      <- Same vars_written as Index 2
  vars_read: var_b
}

Index 4 parameters: {
  address: 4
  vars_written: var_e   
  vars_read: var_c         <- var_c was overwritten in Index 3, should NOT map to Index 2
}

Produces:

1 -[USED_BY]-> 2
1 -[USED_BY]-> 3
2 -[USED_BY]-> 4   (This should not be made because 3 should only map to 4!)
3 -[USED_BY]-> 4

Upvotes: 1

Views: 49

Answers (1)

Shawn
Shawn

Reputation: 363

Credit to the Neo4J team for answering on their Slack channel:

MATCH (i:Instruction), (i2:Instruction)
 WHERE i.address < i2.address AND i.vars_written = i2.vars_read
WITH i, i2 ORDER BY i2.address ASC // <-- order the i2 by it's address
WITH i, head(collect(i2)) as i2 // <-- collect all of the matches and take the first
MERGE (i)-[r:USED_BY]->(i2)
RETURN i, i2, r

Upvotes: 1

Related Questions