Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/11286090 to your computer and use it in GitHub Desktop.
Save kenwebb/11286090 to your computer and use it in GitHub Desktop.
Neo4j Movie-Actor example
<?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