简体   繁体   中英

How to create a d3 radial-tree from a list of nodes and links?

I extract nodes and relationships from a neo4j database using the following cypher query: match p=(:Root) <-[:linkedTo]- () unwind nodes(p) as n unwind rels(p) as r return {nodes: collect(distinct n), links: collect(distinct {source: id(endNode(r)), target: id(startNode(r))})}

I convert the result of the query to arrays of nodes and links as follow:

var obj = JSON.parse(xmlhttp.responseText);
var json = obj.data[0][0];
// Extract node list from neo4j/json data
var nodes = [];
for (n in json.nodes) {
    var nodeObj = json.nodes[n];
    var node = nodeObj.data;
    node.id = nodeObj.metadata.id;
    node.type = nodeObj.metadata.labels[0];
    nodes.push(node);
}
// Create a node map
var nodeMap = {};
nodes.forEach(function(x) { nodeMap['_'+x.id] = x; nodeMap['_'+x.id].children = []; });

// Extract link list from neo4j/json data
var links = json.links.map(function(x) {
        nodeMap['_'+x.source].children.push(nodeMap['_'+x.target]);
        return { source: nodeMap['_'+x.source], target: nodeMap['_'+x.target] };
    });

How should I generate a tree in d3 from the nodes and links? Console.log() shows that both the node and link arrays have the proper format, each node also contains the list of its children.

As mentioned above, the data structure was correct with nodes and children. The missing part was the root node. I therefore changed the cypher query to identify the root node, which appends to be named root in my graph, as follow:

match p=(:Panel) <-[:belongsTo]- (), (root:Panel {Name: "root"}) 
unwind nodes(p) as n unwind rels(p) as r 
return {root: id(root), nodes: collect(distinct n), links: collect(distinct {source: id(endNode(r)), target: id(startNode(r))})}

Hence, the tree is declared as suggested in http://bl.ocks.org/d3noob/8324872 :

var tree = d3.layout.tree()
    .size([360, radius - 120]);

var diagonal = d3.svg.diagonal.radial()
    .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });

var vis = d3.select("#chart").append("svg")
    .attr("width", radius * 2)
    .attr("height", radius * 2 - 150)
    .append("g")
    .attr("transform", "translate(" + radius + "," + radius + ")");

// Compute the new tree layout starting with root
var root = nodeMap['_'+json.root];
var nodes = tree.nodes(root).reverse(), links = tree.links(nodes);
...

To summarize, the trick is to report root, nodes and links from neo4j in JSON format, then build a node array, a node map and assign children to nodes in the node map based on the links.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM