NoSQL Zone is brought to you in partnership with:

Mark is a graph advocate and field engineer for Neo Technology, the company behind the Neo4j graph database. As a field engineer, Mark helps customers embrace graph data and Neo4j building sophisticated solutions to challenging data problems. When he's not with customers Mark is a developer on Neo4j and writes his experiences of being a graphista on a popular blog at http://markhneedham.com/blog. He tweets at @markhneedham. Mark is a DZone MVB and is not an employee of DZone and has posted 534 posts at DZone. You can read more from them at their website. View Full User Profile

Thoughts on Software Development neo4j/cypher: CypherTypeException: Failed merging Number with Relationship

03.25.2013
| 2540 views |
  • submit to reddit

The latest thing that I added to my football graph was the matches that are shown on TV as I have the belief that players who score on televised games get more attention than players who score in other games.

I thought it’d be interesting to work out who the top scorers are on each of these game types.

I added the following relationship type to allow me to do this:

game-[:on_tv]-channel

I then wrote a query to get a list of all the players along with a collection of the games they played in and whether or not this game was televised:

START player=node:players('name:*')
MATCH player-[:played|subbed_on]-stats-[:in]-game-[t?:on_tv]-channel
RETURN player.name, COLLECT([stats.goals, t]) AS games
LIMIT 10

Unfortunately when I ran this query I ended up with the following exception:

CypherTypeException: Failed merging Number with Relationship

From some previous conversations with Wes I’d noticed that this exception didn’t seem to happen with the 1.9.M05 release but I was using 1.9.M04.

Just to see what happened I tried returning the type of the relationship in the collection literal rather than the relationship and that worked:

START player=node:players('name:*')
MATCH player-[:played|subbed_on]-stats-[:in]-game-[t?:on_tv]-channel
RETURN player.name, COLLECT([stats.goals, TYPE(t)]) AS games
LIMIT 10
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| player.name          | games                                                                                                                                                                                                                                                                             |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "Djibril Cissé"      | [[0,<null>],[1,"on_tv"],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[1,<null>],[0,"on_tv"],[0,"on_tv"],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[1,<null>]]                                                                      |
| "Markus Rosenberg"   | [[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,"on_tv"],[0,<null>],[0,"on_tv"],[0,<null>]]                                                                                              |
| "Gabriel Agbonlahor" | [[0,"on_tv"],[1,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,"on_tv"],[1,<null>],[0,"on_tv"],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[1,"on_tv"],[1,<null>],[0,<null>],[0,"on_tv"],[1,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>]]                                   |
| "Shaun Derry"        | [[0,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,"on_tv"]]                                                                                                                    |
| "Marouane Fellaini"  | [[0,<null>],[0,"on_tv"],[0,<null>],[1,<null>],[1,"on_tv"],[1,<null>],[0,<null>],[0,"on_tv"],[1,"on_tv"],[0,<null>],[0,"on_tv"],[2,<null>],[1,<null>],[1,<null>],[1,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[2,<null>],[0,"on_tv"],[0,<null>],[0,"on_tv"]] |
| "Jermaine Jenas"     | [[0,<null>],[1,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[1,<null>]]                                                                                                                                                                                                   |
| "Sean Morrison"      | [[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[1,<null>],[0,"on_tv"],[1,"on_tv"],[0,<null>],[0,"on_tv"]]                                                                                                                                                                          |
| "Claudio Yacob"      | [[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,"on_tv"],[0,<null>],[0,<null>],[0,"on_tv"],[0,"on_tv"],[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>],[0,<null>],[0,<null>]]                         |
| "Michael Owen"       | [[0,<null>],[0,<null>],[0,<null>],[0,<null>],[1,<null>],[0,<null>]]                                                                                                                                                                                                               |
| "Tony Hibbert"       | [[0,"on_tv"],[0,"on_tv"],[0,<null>],[0,<null>],[0,<null>]]                                                                                                                                                                                                                        |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
10 rows
+--------------------------------------------------------+
| player.name        | nonTvGoals | tvGoals | totalGoals |
+--------------------------------------------------------+
| "Gareth Bale"      | 4          | 12      | 16         |
| "Robin Van Persie" | 8          | 11      | 19         |
| "Luis Suárez"      | 12         | 10      | 22         |
| "Theo Walcott"     | 3          | 8       | 11         |
| "Demba Ba"         | 7          | 8       | 15         |
| "Santi Cazorla"    | 4          | 7       | 11         |
| "Carlos Tevez"     | 3          | 6       | 9          |
| "Edin Dzeko"       | 6          | 6       | 12         |
| "Wayne Rooney"     | 6          | 6       | 12         |
| "Juan Mata"        | 4          | 6       | 10         |
+--------------------------------------------------------+
10 rows

So as we can see Gareth Bale pretty much only scores when TV cameras are about!

I was intrigued what had changed between 1.9.M04 and 1.9.M05 so I spent a few hours this morning browsing the cypher part of the code base and not really getting anywhere for the most part.

I thought that there had probably been a change around the way that collection literals were handled but a quick scan of git log suggested there hadn’t been any changes:

$ git log -- community/cypher/src/main/scala/org/neo4j/cypher/internal/parser/v1_9
commit 7311bbe33bc06b346e60e12a4eee2a7173cbd317
Author: Andres Taylor <andres@neotechnology.com>
Date:   Tue Mar 19 06:42:49 2013 +0100
 
    Handles single node patterns in MATCH
 
commit c9f580456572d3d267a15dc88b35e07fd450cf93
Author: Stefan Plantikow <stefan.plantikow@googlemail.com>
Date:   Fri Jan 11 21:27:55 2013 +0100
 
    scala 2.10 support: Kills type erasure warnings with a few casts and cleans up a bit
...

1.9.M04 was released on January 22nd and 1.9.M05 on March 6th and the only commit in this part of the code base in that time didn’t touch the bit of code I’d been looking at.

Interestingly I couldn’t find anywhere in the code base which had the string ‘Failed merging’ so I thought I’d do a quick scan of the diffs to see if this had been deleted:

$ git log -S"Failed merging"
commit b6501aac03cf70419e94b4cfc160695e4950914a
Author: Andres Taylor <andres@neotechnology.com>
Date:   Sat Feb 16 19:30:00 2013 +0100
 
    Changed how Cypher merges types

So in fact there was a commit which changed the way that the collection type was determined so that rather than throwing an exception for clashing types a parent type would be used instead.

In any case this merging problem doesn’t exist in 1.9.M05 and I’ve switched my graph to use that version of neo4j so I won’t be see in this exception anymore!






Published at DZone with permission of Mark Needham, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)