2016-05-02 8 views
0

Ich versuche, eine Hierarchie unter Verwendung eines D3-Baums mit einigen zusätzlichen Felddetails darzustellen. Jetzt bin ich mir nicht sicher/weiß nicht, wie man den erforderlichen JSON für das D3-Baumdiagramm erhält; direkt von den Java neo4j APIs. Aus irgendeinem Grund verwenden wir Embedded Neo4j und Web-Service auf Neo4j.Neo4j Ergebnis (im JSON-Format) zum Erstellen von D3-Baumdiagramm

Ratsuchende und Beispiel-Java-Code, um die folgenden JSON-Format für die Beziehung Herstellung:

Ein Beispiel Json und die D3 Implementierung ist unten angegeben.

Domain Model:

(Switch)-[:CONNECTED_TO]->(Switch) 

Verwendung des JSON-Format (siehe unten) ich einen D3 Baum wie unten

var json = 
 
    { 
 
    "name": "Start", 
 
    "display" : "Entry", 
 
    "parent": "null", 
 
    "children": [ 
 
    { 
 
     "name": "Swith-1", 
 
     "display": "United States of America Entry Swith", 
 
     "parent": "Start", 
 
     "children": [ 
 
     { 
 
      "name": "Swith-1.1", 
 
     \t "display": "IL Entry Swith", 
 
      "parent": "Swith-1", 
 
      "children": [ 
 
\t \t \t \t   { 
 
\t \t \t \t   "name": "Swith-1.1.1", 
 
\t \t \t \t  \t "display": "Chicago Entry Swith", 
 
\t \t \t \t   "parent": "Swith-1.1" 
 
\t \t \t \t   }, 
 
\t \t \t \t   { 
 
\t \t \t \t   "name": "Swith-1.1.2", 
 
\t \t \t \t  \t "display": "Springfield Entry Swith", 
 
\t \t \t \t   "parent": "Swith-1.1" 
 
\t \t \t \t   } 
 
\t \t \t \t  ] 
 
     }, 
 
     { 
 
      "name": "Swith-1.2", 
 
     \t "display": "CA Entry Swith", 
 
      "parent": "Swith-1" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Swith-2", 
 
     "display": "External gateways", 
 
     "parent": "Start" 
 
    } 
 
    ] 
 
}; 
 

 
var width = 700; 
 
var height = 650; 
 
var maxLabel = 150; 
 
var duration = 500; 
 
var radius = 5; 
 
    
 
var i = 0; 
 
var root; 
 

 
var tree = d3.layout.tree() 
 
    .size([height, width]); 
 

 
var diagonal = d3.svg.diagonal() 
 
    .projection(function(d) { return [d.y, d.x]; }); 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width) 
 
    .attr("height", height) 
 
     .append("g") 
 
     .attr("transform", "translate(" + maxLabel + ",0)"); 
 

 
root = json; 
 
root.x0 = height/2; 
 
root.y0 = 0; 
 

 
root.children.forEach(collapse); 
 

 
function update(source) 
 
{ 
 
    // Compute the new tree layout. 
 
    var nodes = tree.nodes(root).reverse(); 
 
    var links = tree.links(nodes); 
 

 
    // Normalize for fixed-depth. 
 
    nodes.forEach(function(d) { d.y = d.depth * maxLabel; }); 
 

 
    // Update the nodes… 
 
    var node = svg.selectAll("g.node") 
 
     .data(nodes, function(d){ 
 
      return d.id || (d.id = ++i); 
 
     }); 
 

 
    // Enter any new nodes at the parent's previous position. 
 
    var nodeEnter = node.enter() 
 
     .append("g") 
 
     .attr("class", "node") 
 
     .attr("transform", function(d){ return "translate(" + source.y0 + "," + source.x0 + ")"; }) 
 
     .on("click", click); 
 

 
    nodeEnter.append("circle") 
 
     .attr("r", 0) 
 
     .style("fill", function(d){ 
 
      return d._children ? "lightsteelblue" : "white"; 
 
     }); 
 

 
    nodeEnter.append("text") 
 
     .attr("x", function(d){ 
 
      var spacing = computeRadius(d) + 5; 
 
      return d.children || d._children ? -spacing : spacing; 
 
     }) 
 
     .attr("dy", "3") 
 
     .attr("text-anchor", function(d){ return d.children || d._children ? "end" : "start"; }) 
 
     .text(function(d){ return d.name; }) 
 
     .style("fill-opacity", 0); 
 

 
    // Transition nodes to their new position. 
 
    var nodeUpdate = node.transition() 
 
     .duration(duration) 
 
     .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); 
 

 
    nodeUpdate.select("circle") 
 
     .attr("r", function(d){ return computeRadius(d); }) 
 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 
 

 
    nodeUpdate.select("text").style("fill-opacity", 1); 
 

 
    // Transition exiting nodes to the parent's new position. 
 
    var nodeExit = node.exit().transition() 
 
     .duration(duration) 
 
     .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) 
 
     .remove(); 
 

 
    nodeExit.select("circle").attr("r", 0); 
 
    nodeExit.select("text").style("fill-opacity", 0); 
 

 
    // Update the links… 
 
    var link = svg.selectAll("path.link") 
 
     .data(links, function(d){ return d.target.id; }); 
 

 
    // Enter any new links at the parent's previous position. 
 
    link.enter().insert("path", "g") 
 
     .attr("class", "link") 
 
     .attr("d", function(d){ 
 
      var o = {x: source.x0, y: source.y0}; 
 
      return diagonal({source: o, target: o}); 
 
     }); 
 

 
    // Transition links to their new position. 
 
    link.transition() 
 
     .duration(duration) 
 
     .attr("d", diagonal); 
 

 
    // Transition exiting nodes to the parent's new position. 
 
    link.exit().transition() 
 
     .duration(duration) 
 
     .attr("d", function(d){ 
 
      var o = {x: source.x, y: source.y}; 
 
      return diagonal({source: o, target: o}); 
 
     }) 
 
     .remove(); 
 

 
    // Stash the old positions for transition. 
 
    nodes.forEach(function(d){ 
 
     d.x0 = d.x; 
 
     d.y0 = d.y; 
 
    }); 
 
} 
 

 
function computeRadius(d) 
 
{ 
 
    if(d.children || d._children) return radius + (radius * nbEndNodes(d)/10); 
 
    else return radius; 
 
} 
 

 
function nbEndNodes(n) 
 
{ 
 
    nb = 0;  
 
    if(n.children){ 
 
     n.children.forEach(function(c){ 
 
      nb += nbEndNodes(c); 
 
     }); 
 
    } 
 
    else if(n._children){ 
 
     n._children.forEach(function(c){ 
 
      nb += nbEndNodes(c); 
 
     }); 
 
    } 
 
    else nb++; 
 
    
 
    return nb; 
 
} 
 

 
function click(d) 
 
{ 
 
    if (d.children){ 
 
     d._children = d.children; 
 
     d.children = null; 
 
    } 
 
    else{ 
 
     d.children = d._children; 
 
     d._children = null; 
 
    } 
 
    update(d); 
 
} 
 

 
function collapse(d){ 
 
    if (d.children){ 
 
     d._children = d.children; 
 
     d._children.forEach(collapse); 
 
     d.children = null; 
 
    } 
 
} 
 

 
update(root);
html{ 
 
    font: 10px sans-serif; 
 
} 
 

 
svg{ 
 
    border: 1px solid silver; 
 
} 
 

 
.node{ 
 
    cursor: pointer; 
 
} 
 

 
.node circle{ 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
} 
 

 
.link{ 
 
    fill: none; 
 
    stroke: lightgray; 
 
    stroke-width: 1.5px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id=tree></div>

+0

Um mehr Informationen, als alternative Option hinzufügen, ich habe auch versucht, die folgende Abfrage das Ergebnis in einzelner „Zeile“ JSON zu extrahieren. Leider kommen die Ergebnisse in mehreren Zeilen: Cypher ----------------------------------- ----- ** MATCH (a: Schalter {Name: "Entry1"}) - [: CONNECTED_TO] -> (Kind) - [: CONNECTED_TO] -> (Enkelkind) MIT Kind, Enkelkind RETURN { name: child.name, children: collect ({name: enkild.name})} als Dokument ** – eShark

+0

Mit der folgenden Abfrage wurde ebenfalls versucht, einen flachen Wert zu erhalten: ** MATCH tree = (a: Switch {name : "Entry1"}) - [: CONNECTED_TO * 1 ..50] -> (Kind) RETURN-Baum, Länge (Baum), [n in Knoten (Baum) | n.name] als Namen ** – eShark

Antwort

0
generieren möchten 0 Ich habe etwas ähnliches in node.js gemacht, sollte in Java ähnlich sein, weil die CIPHER Abfragesyntax die gleiche ist.

Ein Beispiel des Endergebnisses: http://visualize-terms.herokuapp.com/terms/6

Für die nodes und die links bekommen, sehen meine Quellcode:
https://github.com/paradite/Graphpedia/blob/master/models/term.js

Besonders Term.prototype.getOutgoingAndOthers und Term.get (die die neo4j npm-Paket verwendet, aber Sie haben Zugriff auf den Quellcode)

Die Chiffre zum Abrufen der ausgehenden Links für einen Knoten ist:siehe 210

//Construct neo4j raw query 
var query = [ 
    'MATCH (term:Term), (other:Term)', 
    'OPTIONAL MATCH (term) -[relall]-> (other)', 
    'WHERE ID(term) = {termId}', 
    'RETURN other, COUNT(relall), type(relall)', 
    // COUNT(rel) is a hack for 1 or 0, 1 indicates there is an outgoing relationship. 
].join('\n') 

Für sie in d3.js Objekte für den Einsatz in tree layout Parsen:
https://github.com/paradite/Graphpedia/blob/master/routes/terms.js#L108
Siehe exports.show Funktion.

0

Endlich kann ich es bekommen. Hier wird der Rohcode eingefügt. Es erfordert auf jeden Fall Bereinigung aber:

Haupt Logic ....

@GET 
@javax.ws.rs.Path("/getTree/{name}/") 
@Produces({ "application/json" }) 
public Response getTree(@PathParam("name") final String name, @Context final GraphDatabaseService db) 
     throws IOException { 

    System.out.println(" Attribute Name To SearchByName: " + name); 

    HashMap<Long, TreeNode> treeNodeMap = new HashMap<Long, TreeNode>(); 

    TreeNode rootNode = null; 

    String attrubute = "name"; 

    try (Transaction tx = db.beginTx()) { 
     final Node swtch = db.findNode(Labels.Switch, attrubute, name); 
     if (swtch != null) { 
      TraversalDescription td = db.traversalDescription().depthFirst() 
        .expand(PathExpanders.forTypeAndDirection(RelationshipTypes.CONNECTED_TO, Direction.OUTGOING)); 

      for (Path directoryPath : td.traverse(swtch)) 
      { 
       Iterable<Relationship> connectedTos = directoryPath.endNode().getRelationships(Direction.OUTGOING,RelationshipTypes.CONNECTED_TO); 

       if (connectedTos != null) 
       { 
        for(Relationship connectedTo : connectedTos) 
        { 
         //For the Current Relationship 
         //get the start node as parent 
         Node parentNode = connectedTo.getStartNode(); 
         Long parentNodeId = parentNode.getId(); 
         TreeNode parentTreeNode = treeNodeMap.get(parentNodeId); 

         if(parentTreeNode == null) 
         { 
          ////Populate the Parent Details 
          parentTreeNode = new TreeNode(parentNode.getProperty("name", "NoName").toString()); 
          if(rootNode == null) 
           rootNode = parentTreeNode; 
          //Add to the linear HashMap for subsequent searches 
          treeNodeMap.put(parentNodeId, parentTreeNode); 
         } 

         //For the Current Relationship get the end node Children 
         Node childNode = connectedTo.getEndNode(); 
         Long childNodeId = childNode.getId(); 
         TreeNode childTreeNode = treeNodeMap.get(childNodeId); 

         if(childTreeNode == null) 
         { 
          childTreeNode = new TreeNode(childNode.getProperty("name", "NoName").toString()); 
          treeNodeMap.put(childNodeId, childTreeNode); 
          parentTreeNode.setChildren(childTreeNode); 
         } 
        } 
      } 
     } 
     tx.success(); 
    } 
    } 
    /* 
    System.out.println("JSON: " + objectMapper.writeValueAsString(rootNode)); 
    System.out.println("LinearHashMap: " + objectMapper.writeValueAsString(treeNodeMap)); 
    */ 

    return Response.ok().entity(objectMapper.writeValueAsString(rootNode)).build(); 

} 
Verwandte Themen