Merging relationship direction dependent on parameters

178 views Asked by At

I'm having a map list like:

rels: [{"nodeid":14, "direction":false}, {"nodeid":15, "direction":true}]

I'd like to create relationships between the created node and the given nodes with the respective direction:

CREATE (n) WITH n
UNWIND {rels} AS rel
    MATCH (p) WHERE ID(p)=rel.nodeid
WITH n, p
    CASE
         WHEN rel.direction=false THEN
             MERGE (n)-[:test]->(p)
         ELSE
             MERGE (n)<-[:test]-(p)
    END
RETURN id(n)

yields:

Invalid input 'S': expected 'l/L' (line 5, column 11 (offset: 108)) " CASE" ^

CREATE (n%-(:%s%) {properties})
WITH n
UNWIND {rels} AS rel MATCH (p) WHERE ID(p)=rel.nodeid
WITH n,p
MERGE 
    (CASE 
        WHEN rel.direction=true THEN (p)<-[:test]-(n)
        ELSE (p)-[:test1]->(n)
    END)

yields:

Invalid input 'W': expected whitespace, comment, node labels, MapLiteral, a parameter, ')' or a relationship pattern (line 5, column 33 (offset: 174)) " MERGE (CASE WHEN

How would I accomplish this?

 

EDIT:

What I have so far:

CREATE (n {properties})
            WITH n,
            filter(x IN {rels} WHERE x.direction = true) AS outs,
            filter(x IN {rels} WHERE x.direction = false) AS ins
            UNWIND outs as out
                 OPTIONAL MATCH (o) WHERE ID(o)=out.id
                 FOREACH ( y IN CASE WHEN o IS NULL THEN [] ELSE [1] END |
                     MERGE (n)-[:test]->(o) )
            WITH n, ins
            UNWIND ins as in
                 OPTIONAL MATCH (i) WHERE ID(i)=in.id
                 FOREACH ( y IN CASE WHEN i IS NULL THEN [] ELSE [1] END |
                     MERGE (n)<-[:test]-(i) )
            RETURN id(n)

The RETURN id(n) works only when ins and outs is not empty. And if multiple elements exist in ins or outs it returns id(n) length(ins)*length(outs) times, which is not really what is needed.

So: How to return id(n) in all cases and only once?

 

EDIT2:

I'm now using a CASE in UNWIND so it is guaranteed to return the created node ID even if {rels} is empty. Also LIMIT 1 in the return statement guarantees only one row to be returned.

CREATE (n {properties})
            WITH n,
            filter(x IN {rels} WHERE x.direction = true) AS outs,
            filter(x IN {rels} WHERE x.direction = false) AS ins
            UNWIND (CASE WHEN length(outs) > 0 THEN outs ELSE [{id:-1}] END) as out
                 OPTIONAL MATCH (o) WHERE ID(o)=out.id
                 FOREACH ( y IN CASE WHEN o IS NULL THEN [] ELSE [1] END |
                     MERGE (n)-[r:child]->(o))
            WITH n, ins
            UNWIND (CASE WHEN length(ins) > 0 THEN ins ELSE [{id:-1}] END) as in
                 OPTIONAL MATCH (i) WHERE ID(i)=in.id
                 FOREACH ( y IN CASE WHEN i IS NULL THEN [] ELSE [1] END |
                     MERGE (n)<-[r:child]-(i) )
            RETURN id(n) LIMIT 1

Pretty sure this is not perfect, but it's doing the job.

1

There are 1 answers

2
Christophe Willemsen On

You can create two distinct collections from your initial rels collection and UNWIND them, a simple example :

WITH [{id:14, direction:false},{id:15, direction:true}] AS rels 
CREATE (n:Node) 
WITH n,
filter(x IN rels WHERE x.direction = true) AS outs, 
filter(x IN rels WHERE x.direction = false) AS ins 
UNWIND outs as out 
MERGE (o:Node {id: out.id}) 
MERGE (o)-[:OUT]->(n) 
WITH n, ins UNWIND ins AS in 
MERGE (i:Node {id: in.id}) 
MERGE (i)<-[:IN]-(n)

Test it here :

http://console.neo4j.org/?id=iv5opz

enter image description here