官网:
JavaScript graph visualization: the KeyLines toolkit. (Keylines)
Graph Data Platform | Graph Database Management System | Neo4j (Neo4j)
Keylines 订阅制的软件,成为会员后能取得大量的 sample code,强大的 Graph visualization 工具。
Keylines 使用 JSON 资料格式, ex:
{
type: 'LinkChart',
items: [
{
type:'node',
id: 1,
t:'hello'
},
{
type:'link',
id1:'8',
id2:'7',
id:'8-8'
}
]
}
基本就是 Node & Link,type 一律为 'LinkChart', items 中 node 中的 id 需为唯一, link 亦然
Springboot 做为 RESTful API,引用
- spring-boot-starter-web
- spring-boot-starter-thymeleaf
Neo4j 为后端资料库
Neo4j 似乎会依 cypher 语法不同儿回传略有不同的资料格式,但基本都是以下四类:
- NODE
- RELATIONSHIP
- list of any?
- path
String type = val.type().name().toLowerCase();
switch (type.toUpperCase()) {
case "NODE":
break;
case "RELATIONSHIP":
break;
case "path":
value.asList(Service::convert); // 回呼
break;
case "list of any?":
break;
default:
logger.info(type);
break;
}
还有就是 neo4j 会回传重复的 Node or Relationship,在回传给 keyliens 前需处理
public static String keylinesJson(final List<Result> list, final String condition1) {
Map<Long, Node> nodeMap = new Hashtable<>();
Map<Long, Link> rMap = new Hashtable<>();
list.forEach(result -> {
while (result.hasNext()) {
Iterator<Value> it = result.next().values().iterator();
while (it.hasNext()) {
Value val = it.next();
String type = val.type().name().toLowerCase();
switch (type.toUpperCase()) {
case "NODE":
List<String> label_List = new ArrayList<>();
Iterator<String> it_labels =
val.asNode().labels().iterator();
while (it_labels.hasNext()) {
String str = it_labels.next();
label_List.add(str);
}
Node nJson = new Node();
Map<String, Object> properties = new Hashtable<>();
properties.put("type", label_List.get(0).toLowerCase());
val.asNode().asMap().forEach((k, v) -> {
properties.put(k, v);
});
nJson.d = properties;
long node_id = val.asNode().id();
nJson.id = node_id;
String name = properties.get("NAME")==null ?
label_List.get(0) : properties.get("condition2").toString();
properties.get("condition3").toString();
nJson.t = name;
nodeMap.put(node_id, nJson);
break;
case "RELATIONSHIP":
Link link = new Link();
link.id = val.asRelationship().id();
link.id1 = val.asRelationship().startNodeId();
link.id2 = val.asRelationship().endNodeId();
link.d = val.asRelationship().asMap();
link.type = val.asRelationship().type();
if (link.d.get("LABEL") != null) {
link.t = link.d.get("LABEL").toString();
} else {
link.t = link.type;
}
long relate_id = val.asRelationship().id();
rMap.put(relate_id, link);
break;
case "list of any?":
for (int i = 0; i < val.size(); i++) {
Relationship rship = val.get(i).asRelationship();
Link rlink = new Link();
Map<String, Object> propsMap = new Hashtable<>();
propsMap.put("type", rship.type().toLowerCase());
rship.asMap().forEach((k, v) ->{
propsMap.put(k, v);
});
rlink.d = propsMap;
rlink.id = rship.id();
rlink.id1 = rship.startNodeId();
rlink.id2 = rship.endNodeId();
if (rlink.d.get("LABEL") != null) {
rlink.t = rlink.d.get("LABEL").toString();
} else {
rlink.t = rlink.type;
}
rMap.put(rlink.id, rlink);
}
break;
case "path":
// 回呼
break;
default:
logger.info(type);
break;
}
}
}
});
LinkChart dataJson = new LinkChart();
nodeMap.forEach((k, v) -> {
dataJson.items.add(v);
});
rMap.forEach((k, v) -> {
dataJson.items.add(v);
});
return new Gson().toJson(dataJson);
}
计划将 node & link 操做留在前端 keylines 处理