14

I have the following graph as a Neo4j graph database:

                           activates
                            (80 °F)
          (A)------------------------------------->(D)
           | \__                                _/->^
           |    \__  activates               __/    |
           |       \__(50 °F)             __/       |
           |          \__              __/          |             
           |             \__        __/             | 
activates  |                \__  __/                |
 (50 °F)   |                   \/                   | activates
           |                 __/\__                 | (50 °F)
           |    activates __/      \__              |
           |    (60 °F)__/            \__           |
           |        __/                  \__        |
           |     __/                        \__     |
           |  __/                              \_   |
           v /                                   \->|
          (B)------------------------------------->(C)
                           activates                          
                            (50 °F)

Each relationship has a property denoting the required temperature for the 'activates' action.

I need to retrieve all the available paths between (A) and (D) WHERE the temperature is 50 °F along the path.

The output should include:

A -[:activates{temperature:'50'}]-> B -[:activates{temperature:'50'}]-> C -[:activates{temperature:'50'}]-> D

A -[:activates{temperature:'50'}]-> C -[:activates{temperature:'50'}]-> D

but not

A -[:activates{temperature:'80'}]-> D

A -[:activates{temperature:'50'}]-> B -[:activates{temperature:'60'}]-> D

How do I write the required Cypher query?

Thanks in advance.

Edit 1: I added another diagonal relationship (B -[:activates{temperature:'80'}]-> D) for more clarity.

Edit 2: I need to retrieve all the available paths between (A) and (D) WHERE the temperature is the same along the path, i.e: A -> B -> C -> D, A -> C -> D, A -> D.

Orion
  • 1,104
  • 3
  • 16
  • 40
  • What have you tried so far? This can be done in cypher, but we'd like to see that you have tried something rather then just give you the solution outright. – Nicholas Dec 31 '12 at 19:23
  • My thought is to retrieve all the possible paths, then choose only the uniform paths using a Java code. But I think Cypher query can help in this scenario. – Orion Dec 31 '12 at 22:30
  • http://docs.neo4j.org/chunked/stable/query-match.html#match-variable-length-relationships – Nicholas Jan 01 '13 at 02:24
  • 1
    just do an examples graph to play around with at console.neo4j.org? – Peter Neubauer Jan 02 '13 at 14:37
  • Here is an example http://console.neo4j.org/?id=is8ao2. I modified it so it describes my scenario more accurately. In short, I need to find all paths from A to D where all the parts (relationships) of the matched path should have the same property. The result should include A -> B -> D (where temp = 50 along the path) -and- A -> C -> D (where temp = 60 along the path). Please see the "bus scenario" in my comment to ulkas (below). – Orion Jan 03 '13 at 10:15

1 Answers1

18
START a=node({A}), d=node({D})
MATCH p=a-[r:ACTIVATES*..]-d
WHERE has(r.temperature) and r.temperature='50'
RETURN p;

substitute the values in the curved brackets (A,D) with their node IDs

update: using function all

START a=node(1), d=node(4) 
MATCH p=a-[r:ACTIVATES*..]-d 
WITH head(relationships(p))as r1,p //since the pointer r is a collection of rels we must declare a single relationship pointer
WHERE all(r2 in relationships(p) 
          where r2.temperature=r1.temperature) 
return p;
ulkas
  • 5,748
  • 5
  • 33
  • 47
  • Thank you ulkas. Your answer completely answers the above scenario. However, I realized that the scenario should be more complex: all the relationships in one path should have common properties (temp=50 OR 60 OR ...), whatever they are. It is similar to bus paths, where you can travel from A to B via paths each of which is used by only one bus--whatever it is. If you think I need to post the modified scenario as a new question, I can gladly accept your answer here. ;) – Orion Jan 03 '13 at 09:20
  • This is cool, I wonder if it can be expanded into more general logic. It lends itself perfectly to the paths / arcs problem, obviously, but more general logic (along the lines of prolog) so if I have an 'is' relationship and if one node 'is' another, then it 'has' all the edges of the other node so edge(a,p,b) :- (a)-[:p]->(b) edge(a,p,b) :- (a)-[ :is* ]->( x ) AND (x)-[:p]>(b) But this of course could theoretically become a lot more general. I dont know if it's clear what I'm trying to say... I'm not very communicative today –  Apr 12 '17 at 15:51
  • 2
    For neo4j 3.4 I used this: MATCH p=(a:Database)-[r:PARENTS*..]-(d:Database) WHERE a.membershipID = 'H1001' and d.membershipID = "H12412" RETURN p; – Mesh Manuel Nov 27 '18 at 05:38