Reputation: 2481
I have been modeling some data related to call paths. A call enters the system, then maybe someone answers, then someone transfers, then someone hangs up, maybe some other stuff happens in between. Since they are ordered from beginning to end, I decided to model them as a linked list:
(call:Call)-[r:NextEvent]->(e:Event)-[r:NextEvent]->(e:Event)
and so on for as many events as there are. To query all the events that happen on a call I can go:
neo4j-sh (?) $ match (call:Call)-[:NextEvent*]->(lastEvent:Event) where call.callid="123"
> return lastEvent;
+------------------------------------------------------------------------------------------------------+
| lastEvent |
+------------------------------------------------------------------------------------------------------+
| Node[22]{name:"Newcall",callerid:"1231231234",calleridname:"David Foo",destination:"3213214321"} |
| Node[24]{name:"EnterQueue"} |
| Node[27]{name:"RingAttempt"} |
+------------------------------------------------------------------------------------------------------+
That's pretty much perfect. When someone enters a queue, I'd like to know what queue they are in, and when a ring attempt is made, I'd like to know the user whose phone rang, so I added some relations.
neo4j-sh (?)$ match (e:Event)-[r:Agent]->(agent:User) where e.name="RingAttempt" return e,agent;
+-----------------------------------------------------------------------------------------------------------------------------------+
| e | agent |
+-----------------------------------------------------------------------------------------------------------------------------------+
| Node[27]{name:"RingAttempt"} | Node[26]{username:"[email protected]"} |
+-----------------------------------------------------------------------------------------------------------------------------------+
neo4j-sh (?)$ match (e:Event)-[r:Queue]->(queue:Queue) where e.name="EnterQueue" return e,queue;
+-------------------------------------------------------------------+
| e | queue |
+-------------------------------------------------------------------+
| Node[24]{name:"EnterQueue"} | Node[17]{name:"Main Support Queue"} |
+-------------------------------------------------------------------+
Now I'd like to run a query that will get each event, and if the event is a ringattempt, also give me the agent it attempted to ring, and if the event is an enterqueue, give me the queue that was entered, so I tried to write this:
neo4j-sh (?)$ match p = (call:Call)-[:NextEvent*]->(lastEvent:Event) where call.callid="123"
> optional match (lastEvent)-[r:Queue]->(queue:Queue) where lastEvent.name="EnterQueue"
> optional match (lastEvent)-[r:Agent]->(agent:User) where lastEvent.name="RingAttempt"
> return lastEvent,queue,agent;
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| lastEvent | queue | agent |
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| Node[22]{name:"Newcall",callerid:"1231231234",calleridname:"David Foo",destination:"3213214321"} | <null> | <null> |
| Node[24]{name:"EnterQueue"} | Node[17]{name:"Main Support Queue"} | <null> |
| Node[27]{name:"RingAttempt"} | <null> | <null> |
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
But why is agent null? I know for a fact that it exists. When I swap the two optional matches in the cypher query, it causes queue to be null and agent will instead be correct. I don't understand why.
Just to be clear I'm using neo4j-community-2.0.0-RC1.
Upvotes: 2
Views: 1761
Reputation: 33175
You're using the same r
identifier for the two optional match relationships, so it's already bound by the time you get to the second optional match, either as null, or as a relationship to a Queue
. So, it will never match the Agent
. Since you don't seem to care about the r
, you can leave that out of the optional match
.
match p = (call:Call)-[:NextEvent*]->(lastEvent:Event) where call.callid="123"
optional match (lastEvent)-[:Queue]->(queue:Queue) where lastEvent.name="EnterQueue"
optional match (lastEvent)-[:Agent]->(agent:User) where lastEvent.name="RingAttempt"
return lastEvent,queue,agent;
Upvotes: 3