Last active
August 29, 2015 14:00
-
-
Save kenwebb/11286090 to your computer and use it in GitHub Desktop.
Neo4j Movie-Actor example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Sat Apr 26 2014 21:43:52 GMT-0400 (EDT)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Neo4j Movie-Actor example | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 11286090 | |
Keywords: | |
My Notes | |
-------- | |
This workbook explores a simple Neo4j[2] example, and various issues that it raises: | |
- how to represent this as a Xholon app using a XholonWorkbook in a gist | |
- what it looks like using the Xholon D3 Circle Pack GUI | |
- how to deal with the many-to-many relationships between actors and movies | |
- Xholon currently doesn't handle arrays of ports with a fieldName other than "port" | |
- can I represent this as a Petri Net | |
- but then I have to deal with the Petri Net arcs in the composite structure hierarchy | |
- how to represent node properties with arbitrary names (ex: year) | |
- how to deal with relationship properties | |
- use a Xholon IPort | |
- use an intermediate Role or MovieRole node | |
- how to show only the roleName for movie and actor nodes, with clsc and d3cp GUI ??? | |
- be able to set a default getName() template | |
- this isn't necessary to do | |
I'm manually converting the Neo4j nodes, relationships and properties to Xholon XML format. | |
I want to be able to do this automatically for any Neo4j content. | |
Quick notes as I work through how to do this: | |
- convert Neo4j/Cypher ' to Xholon/XML " | |
- with Xholon/XML it's better to use " because there may be an embedded XPath expression that requires ' | |
- convert Neo4j/Cypher principle naming property to Xholon roleName | |
- for ports, I'll use the approach I use with state machines, where ports are specified in ClassDetails, | |
and each port specification includes an initial step to identify the source node | |
Graph Setup[1] using the Cypher[3] language: | |
CREATE | |
// Movie nodes | |
(matrix1:Movie { id : '603', title : 'The Matrix', year : '1999-03-31' }), | |
(matrix2:Movie { id : '604', title : 'The Matrix Reloaded', year : '2003-05-07' }), | |
(matrix3:Movie { id : '605', title : 'The Matrix Revolutions', year : '2003-10-27' }), | |
// Actor nodes | |
(neo:Actor { name:'Keanu Reeves' }), | |
(morpheus:Actor { name:'Laurence Fishburne' }), | |
(trinity:Actor { name:'Carrie-Anne Moss' }), | |
// relationships | |
(matrix1)<-[:ACTS_IN { role : 'Neo' }]-(neo), | |
(matrix2)<-[:ACTS_IN { role : 'Neo' }]-(neo), | |
(matrix3)<-[:ACTS_IN { role : 'Neo' }]-(neo), | |
(matrix1)<-[:ACTS_IN { role : 'Morpheus' }]-(morpheus), | |
(matrix2)<-[:ACTS_IN { role : 'Morpheus' }]-(morpheus), | |
(matrix3)<-[:ACTS_IN { role : 'Morpheus' }]-(morpheus), | |
(matrix1)<-[:ACTS_IN { role : 'Trinity' }]-(trinity), | |
(matrix2)<-[:ACTS_IN { role : 'Trinity' }]-(trinity), | |
(matrix3)<-[:ACTS_IN { role : 'Trinity' }]-(trinity) | |
Query[1]: | |
MATCH (a:Actor { name:"Keanu Reeves" }) | |
RETURN a | |
References | |
---------- | |
(1) http://www.neo4j.org/console?id=cineasts | |
(2) http://www.neo4j.org/ | |
(3) http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html | |
]]></Notes> | |
<_-.XholonClass> | |
<!-- domain objects --> | |
<MovieActorSystem/> | |
<Movie/> | |
<Actor/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
<Actor xhType="XhtypePureActiveObject"> | |
<port name="port" index="0" connector=".[@roleName='Keanu Reeves']/../Movie[@roleName='The Matrix']"/> | |
<port name="port" index="1" connector=".[@roleName='Keanu Reeves']/../Movie[@roleName='The Matrix Reloaded']"/> | |
<port name="port" index="2" connector=".[@roleName='Keanu Reeves']/../Movie[@roleName='The Matrix Revolutions']"/> | |
<port name="port" index="0" connector=".[@roleName='Laurence Fishburne']/../Movie[@roleName='The Matrix']"/> | |
<port name="port" index="1" connector=".[@roleName='Laurence Fishburne']/../Movie[@roleName='The Matrix Reloaded']"/> | |
<port name="port" index="2" connector=".[@roleName='Laurence Fishburne']/../Movie[@roleName='The Matrix Revolutions']"/> | |
<port name="port" index="0" connector=".[@roleName='Carrie-Anne Moss']/../Movie[@roleName='The Matrix']"/> | |
<port name="port" index="1" connector=".[@roleName='Carrie-Anne Moss']/../Movie[@roleName='The Matrix Reloaded']"/> | |
<port name="port" index="2" connector=".[@roleName='Carrie-Anne Moss']/../Movie[@roleName='The Matrix Revolutions']"/> | |
</Actor> | |
</xholonClassDetails> | |
<MovieActorSystem> | |
<Movie roleName="The Matrix" year="1999-03-31"/> | |
<Movie roleName="The Matrix Reloaded" year="2003-05-07"/> | |
<Movie roleName="The Matrix Revolutions" year="2003-10-27"/> | |
<Actor roleName="Keanu Reeves"/> | |
<Actor roleName="Laurence Fishburne"/> | |
<Actor roleName="Carrie-Anne Moss"/> | |
</MovieActorSystem> | |
<MovieActorSystembehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
var beh = { | |
postConfigure: function() { | |
//$wnd.xh.param("MaxPorts", "3"); | |
this.writeCypher(); | |
this.cnode.remove(); | |
}, | |
// write out the Xholon app in a Neo4j Cypher format, similar to the original | |
writeCypher: function() { | |
var node = this.cnode.parent().first(); | |
var relationships = ""; | |
while (node) { | |
if (node.xhc().name() == "Movie") { | |
// (matrix1:Movie { id : '603', title : 'The Matrix', year : '1999-03-31' }), | |
node.println("(node" + node.id() + ":Movie { title : '" + node.role() + "', year : '" + node.year + "' }),"); | |
} | |
else if (node.xhc().name() == "Actor") { | |
// (neo:Actor { name:'Keanu Reeves' }), | |
node.println("(node" + node.id() + ":Actor { name : '" + node.role() + "' }),"); | |
// (matrix1)<-[:ACTS_IN { role : 'Neo' }]-(neo), | |
var i = 0; | |
var movie = node.port(i++); | |
while (movie) { | |
relationships = relationships + "(node" + movie.id() + ")<-[:ACTS_IN]-(node" + node.id() + "),\n"; | |
movie = node.port(i++); | |
} | |
} | |
node = node.next(); | |
} | |
this.cnode.parent().println(relationships); | |
} | |
} | |
]]></MovieActorSystembehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Movie</title> | |
<rect id="MovieActorSystem/Movie" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment