赞
踩
效果如下:
搜索李淳罡:
添加节点和关系,在这里添加李淳罡-喜欢-绿袍,如下多出李淳罡和绿袍的关系和绿袍的节点
在neo4j中,存储如下图
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 {
- @Autowired
- private 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;
-
- @Autowired
- public 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 {
- @Autowired
- private 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.nodes
- const relationship = response.relationships
- const 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 = option
-
- this.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].name
- this.entityName = entityName
- this.initData()
- });
-
- myChart.on("mouseover", (chartParam) => {
- console.log(chartParam)
- })
-
- }
- }
- }
- </script>
-
- <style>
- .kgContainer {
- width: 100%;
- background-color: #FFFFFF;
- padding: 32px;
- }
-
- .kgShow {
- width: 100%;
- height: 500px;
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。