当前位置: 代码迷 >> 综合 >> 利用Spring boot、neo4j、echarts可视化雪中悍刀行
  详细解决方案

利用Spring boot、neo4j、echarts可视化雪中悍刀行

热度:14   发布时间:2023-10-12 09:13:15.0

效果如下:

利用Spring boot、neo4j、echarts可视化雪中悍刀行

搜索李淳罡:

 利用Spring boot、neo4j、echarts可视化雪中悍刀行

添加节点和关系,在这里添加李淳罡-喜欢-绿袍,如下多出李淳罡和绿袍的关系和绿袍的节点

利用Spring boot、neo4j、echarts可视化雪中悍刀行 

利用Spring boot、neo4j、echarts可视化雪中悍刀行

在neo4j中,存储如下图

利用Spring boot、neo4j、echarts可视化雪中悍刀行

SDN似乎无法任意存储关系,故在这里使用的neo4j-java-driver完成的以上功能:

[neo4jConfig.java]

加载驱动和提供session

package com.sandalen.water.config;import com.sandalen.water.PropertiesClass.Neo4jProperties;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class Neo4jConfig {@Autowiredprivate Neo4jProperties neo4jProperties;@Bean(name="NeoSession")public Session initDriver(){Session session = null;try{Driver driver = GraphDatabase.driver(neo4jProperties.getURI(), AuthTokens.basic(neo4jProperties.getUsername(), neo4jProperties.getPassword()));session = driver.session();return session;}catch (Exception e){e.printStackTrace();return session;}}
}

 [CypherUtils.java]

这里主要定义了一些cypher语句

package com.sandalen.water.other;import org.springframework.stereotype.Component;@Component
public class CypherUtils {public static String createSingle(String entity){return "merge (m:Person{name:\""+entity+"\"}) return m";}public static String createRelationByTwoNodes(String entityFrom,String relation,String entityTo){return "match(m:Person{name:\""+entityFrom+"\"}),(n:Person{name:\""+entityTo+"\"}) merge (m)-[r:"+relation+"]->(n) return m,n,r";}public static String searchAll(String entityName){if(entityName == "" || entityName == null){return "match (m)-[edge]->(n) return m,edge,n";}return "match (m)-[edge]-(n) where n.name='" + entityName + "' return m,edge,n";}}

[Neo4jUtils.java]

添加、查找关系和节点的逻辑实现,其中添加的逻辑是先查询输入的两个实体,若任意实体不存在则先创建,再根据这两个节点添加关系。

查找的逻辑很简单,不再赘述。

package com.sandalen.water.util;import com.sandalen.water.other.CypherUtils;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Relationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.*;@Component
public class Neo4jUtils {private static Session session;@Autowiredpublic Neo4jUtils(Session NeoSession){Neo4jUtils.session= NeoSession;}public static boolean create(String entityFrom,String relation,String entityTo){try {StatementResult statementResult = session.run(CypherUtils.createSingle(entityFrom));List<Record> entityFromlist = statementResult.list();StatementResult entityToResult = session.run(CypherUtils.createSingle(entityTo));List<Record> entityToList = entityToResult.list();if(entityFromlist.size() == 0){session.run(CypherUtils.createSingle(entityFrom));}if(entityToList.size() == 0){session.run(CypherUtils.createSingle(entityTo));}StatementResult result = session.run(CypherUtils.createRelationByTwoNodes(entityFrom, relation, entityTo));return true;}catch (Exception e){e.printStackTrace();return false;}}public static Map<String,Object> searchAll(String entityName){StatementResult result = session.run(CypherUtils.searchAll(entityName));List<Record> list = result.list();Map<String,Object> resultMap = new HashMap<>();Set<String> nodes = new HashSet<>();List<String> relationships = new ArrayList<>();for (Record r : list){String start_node = r.get("m").get("name").toString().replace("\"","");String relationship = r.get("edge").asRelationship().type().replace("\"","");String end_node = r.get("n").get("name").toString().replace("\"","");//            System.out.println(start_node + "-" + relationship + "->" + end_node );relationship = start_node + "-" + relationship + "-" + end_node;nodes.add(start_node);nodes.add(end_node);relationships.add(relationship);}resultMap.put("nodes",nodes);resultMap.put("relationships",relationships);return resultMap;}}

[controller]

package com.sandalen.water.controller;import com.sandalen.water.bean.RespBean;
import com.sandalen.water.service.KgService;
import com.sandalen.water.util.Neo4jUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RequestMapping("/kg")
@RestController
public class KgController {@Autowiredprivate KgService kgService;@RequestMapping("/saveEntity")public RespBean saveEntity(String entityFrom,String relation,String entityTo){boolean isCreated = Neo4jUtils.create(entityFrom, relation, entityTo);if(isCreated){return RespBean.ok("创建数据成功");}return RespBean.error("创建失败");}@RequestMapping("/search")public RespBean searchAll(String entityName){Map<String, Object> map = Neo4jUtils.searchAll(entityName);return RespBean.ok("获取数据成功",map);}}

[前端]

前端代码只提供页面的,我使用的是element Ui和vue

<template><div class="kgContainer"><div class="alert alert-info" role="alert" style="margin-bottom: 20px;"><h1>Prompt</h1><font size="4">输入你想要搜索的知识</font></div><div class="search" style="text-align: center;margin-bottom: 50px;"><el-input v-model="entityName" placeholder="请输入内容" style="width: 400px;"></el-input><el-button type="primary" icon="el-icon-search" @click="initData">搜索</el-button><el-input v-model="form.entityFrom" placeholder="请输入内容" style="width: 100px;"></el-input><el-input v-model="form.relation" placeholder="请输入内容" style="width: 100px;"></el-input><el-input v-model="form.entityTo" placeholder="请输入内容" style="width: 100px;"></el-input><el-button type="primary" icon="el-icon-search" @click="add">添加</el-button></div><div class="kgShow" id="kgShow" style="width: 100%;"></div><!--<div class="test" id="tst" style="width: 100%;height: 500px;"></div>--></div>
</template><script>var echarts = require('echarts');export default {data() {return {entityName: '',option: '',form: {entityFrom: '',relation: '',entityTo: ''},nodes: [],relationships: []}},mounted() {this.initData()this.tst()},inject: ['reload'],methods: {initData() {this.$store.dispatch('kg/search', this.entityName).then(response => {const nodes = response.nodesconst relationship = response.relationshipsconst nodesList = []for(let i = 0; i < nodes.length; i++) {const tmp = {name: nodes[i],symbolSize: 50,itemStyle: {normal: {show: true,}}}nodesList.push(tmp)}const links = []for(let i = 0; i < relationship.length; i++) {const relationshipArray = relationship[i].split("-")const tmp = {source: relationshipArray[0],target: relationshipArray[2],name: relationshipArray[1]}links.push(tmp)}const option = {title: {text: '雪中悍刀行'},tooltip: {formatter: function(x) {return x.data.name;}},animationDurationUpdate: 1500,animationEasingUpdate: 'quinticInOut',series: [{type: 'graph',layout: 'force',symbolSize: 80,roam: true,label: {normal: {show: true,}},edgeSymbol: ['circle', 'arrow'],edgeSymbolSize: [4, 10],edgeLabel: {normal: {textStyle: {fontSize: 20}}},force: {repulsion: 3000, //斥力edgeLength: [20, 80] //默认距离},//            layout:'circular',draggable: true,lineStyle: {normal: {width: 2,color: '#4b565b',curveness: 0.2,length: 20}},edgeLabel: {normal: {show: true,formatter: function(x) {return x.data.name;}}},data: nodesList,links: links}]}this.option = optionthis.showKg()})},add() {this.$store.dispatch('kg/save', this.form).then(response => {if(response.status == 200) {this.$message({message: response.msg,type: 'success'})this.reload()}})},getInfo(params) {alert(params)},showKg() {const kgShow = document.getElementById('kgShow')const myChart = echarts.init(kgShow, 'light')myChart.setOption(this.option)let data = myChart._model.option.series[0].data;myChart.on("click", (chartParam) => {//        console.log(myChart._model)//        console.log(chartParam)const entityName = data[chartParam.dataIndex].namethis.entityName = entityNamethis.initData()});myChart.on("mouseover", (chartParam) => {console.log(chartParam)})}}}
</script><style>.kgContainer {width: 100%;background-color: #FFFFFF;padding: 32px;}.kgShow {width: 100%;height: 500px;}
</style>

 

  相关解决方案