I'm building an app based around a d3 force-directed graph with ArangoDB on the backend, and I want to be able to load node and link data dynamically from Arango as efficiently as possible.
I'm not an expert in d3, but in general the force layout seems to want the its data as an array of nodes and an array of links that have the actual node objects as their sources and targets, like so:
var nodes = [
{id: 0, reflexive: false},
{id: 1, reflexive: true },
{id: 2, reflexive: false}
],
links = [
{source: nodes[0], target: nodes[1], left: false, right: true },
{source: nodes[1], target: nodes[2], left: false, right: true }
];
Currently I am using the following AQL query to get neighboring nodes, but it is quite cumbersome. Part of the difficulty is that I want to include edge information for nodes even when those edges are not traversed (in order to display the number of links a node has before loading those links from the database).
LET docId = "ExampleDocClass/1234567"
// get data for all the edges
LET es = GRAPH_EDGES('EdgeClass',docId,{direction:'any',maxDepth:1,includeData:true})
// create an array of all the neighbor nodes
LET vArray = (
FOR v IN GRAPH_TRAVERSAL('EdgeClass',docId[0],'any',{ maxDepth:1})
FOR v1 IN v RETURN v1.vertex
)
// using node array, return inbound and outbound for each node
LET vs = (
FOR v IN vArray
// inbound and outbound are separate queries because I couldn't figure out
// how to get Arango to differentiate inbout and outbound in the query results
LET oe = (FOR oe1 IN GRAPH_EDGES('EdgeClass',v,{direction:'outbound',maxDepth:1,includeData:true}) RETURN oe1._to)
LET ie = (FOR ie1 IN GRAPH_EDGES('EdgeClass',v,{direction:'inbound',maxDepth:1,includeData:true}) RETURN ie1._from)
RETURN {'vertexData': v, 'outEdges': oe, 'inEdges': ie}
)
RETURN {'edges':es,'vertices':vs}
The end output looks like this: http://pastebin.com/raw.php?i=B7uzaWxs ...which can be read almost directly into d3 (I just have to deduplicate a bit).
My graph nodes have a large amount of links, so performance is important (both in terms of load on the server and client, and file size for communication between the two). I am also planning on creating a variety of commands to interact with the graph aside from simply expanding neighboring nodes. Is there a way to better structure this AQL query (e.g. by avoiding four separate graph queries) or avoid AQL altogether using arangojs functions or a FOXX app, while still structuring the response in the format I need for d3 (including link data with each node)?