neo4j是什么?
簡(jiǎn)單來(lái)說(shuō),這是一種比較熱門的圖數(shù)據(jù)庫(kù),圖數(shù)據(jù)庫(kù)以圖形形式存儲(chǔ)數(shù)據(jù)。 它以節(jié)點(diǎn),關(guān)系和屬性的形式存儲(chǔ)應(yīng)用程序的數(shù)據(jù)。 一個(gè)圖由無(wú)數(shù)的節(jié)點(diǎn)和關(guān)系組成。
安裝圖數(shù)據(jù)庫(kù)在這里就不介紹了,本篇主要介紹如何連接neo4j數(shù)據(jù)庫(kù),將知識(shí)圖譜成功顯示在前端頁(yè)面中。
一、Neovis.js 不用獲取數(shù)據(jù)直接連接數(shù)據(jù)庫(kù)繪圖
1.、 Neovis.js與Neo4j的連接非常簡(jiǎn)單明了,并且Neovis 的數(shù)據(jù)格式與那neo4j數(shù)據(jù)庫(kù)保持一致。在單個(gè)配置對(duì)象中定義標(biāo)簽、屬性、節(jié)點(diǎn)和關(guān)系的樣式和顏色。
首先下載依賴
npm install -save neovis.js
在項(xiàng)目中引用
import NeoVis from 'neovis.js';
創(chuàng)建用來(lái)繪圖的DOM元素
<div style="height:100%;" ref="Screen">
<div class="left" id="viz1" ref="viz1"></div>
</div> -->
頁(yè)面加載進(jìn)來(lái)調(diào)用draw()畫圖函數(shù)
mounted() {
this.draw();
},
//neovis.js畫圖
methods:{
draw() {
//獲取dom元素
var viz1 = this.$refs.viz1;
//創(chuàng)建veovis實(shí)例
var viz;
//配置項(xiàng)
var config = {
container_id: "viz",
//neo4j服務(wù)器地址,用戶名 和 密碼
server_url: "bolt://192.x.xxx.10:7687",
server_user: "nexx4j",
server_password: "KGxxx34",
**///labels是節(jié)點(diǎn)央樣式的配置:**
**/// caption :節(jié)點(diǎn)顯示的文字對(duì)應(yīng)內(nèi)容
**/// community: 節(jié)點(diǎn)顏色**
**/// size:節(jié)點(diǎn)大小**
**/// font:節(jié)點(diǎn)字體大小設(shè)置****
**//沒(méi)有在這個(gè)地方配置的節(jié)點(diǎn)將會(huì)是默認(rèn)樣式**
labels: {
"CITY": { caption: "name", community: "#5496FF", size: 200, font: { size: 35, color: "#606266", }, },
"基本待遇政策": { caption: "name", community: "#5496FF", size: 95, font: { size: 25, color: "#606266", } },
"基本籌資政策": { caption: "name", community: "#5496FF", size: 95, font: { size: 25, color: "#606266", }, },
},
**///relationships是關(guān)系線段樣式的配置:**
**/// caption :線段顯示的文字對(duì)應(yīng)內(nèi)容
**/// thickness: 線段粗細(xì)**
**/// font:節(jié)點(diǎn)字體大小設(shè)置****
**//沒(méi)有在這個(gè)地方配置的線段將會(huì)是默認(rèn)樣式**
relationships: {
"待遇支付政策": { thickness: 1, caption: true, font: { size: 15, color: "#606266", }, },
"待遇主體類別": { thickness: "count", caption: true, font: { size: 15, color: "#606266", }, },
},
//是否顯示箭頭
arrows: true,
hierarchical: true,
// 分層結(jié)構(gòu)或者默認(rèn) "hubsize"(默認(rèn))和"directed".
// hierarchical_sort_method: 'hubsize',
hierarchical_sort_method: 'directed',
//配置數(shù)據(jù)庫(kù)查詢語(yǔ)句,MATCH n RETURN n,嘗試過(guò)不對(duì),必須用 MATCH p=()-->() RETURN p
initial_cypher: 'MATCH p=()-->() RETURN p',
};
viz = new NeoVis(config);
viz._container = viz1;
viz.render();
},
}
二、vis.js 或者 echarts繪圖
由于這兩者需要的數(shù)據(jù)格式與neo4j數(shù)據(jù)格式不同,所以需要先從前端獲取數(shù)據(jù),然后處理成我們需要的格式。
1、(發(fā)現(xiàn)一個(gè)神器) neo4j-driver 能夠直接通過(guò)前端獲取數(shù)據(jù)。
上代碼, 首先下載依賴
npm install -save neo4j-driver
再頁(yè)面中引入
var neo4j = require("neo4j-driver");
export default {
...此處暫時(shí)省略...
}
頁(yè)面初次加載調(diào)用 this.executeCypher() 執(zhí)行 Cypher 查詢數(shù)據(jù)
mounted() {
var query= 'MATCH p=()-->() RETURN p'
this.executeCypher(query);
},
executeCypher()方法定義: 該方法處理的數(shù)據(jù)格式為echarts適用格式
/**
* 直接執(zhí)行Cypher
*/
executeCypher(query) {
this.echartsNode = [] //節(jié)點(diǎn)數(shù)組
this.nodesRelation = [] //關(guān)系線數(shù)組
this.category = [] //echarts圖例數(shù)據(jù)數(shù)
// 創(chuàng)建實(shí)例
this.driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'KG****'));
console.log("?? ~ file: AuthorArticleSearch.vue ~ line 46 ~ mounted ~ this.drive", this.driver)
let me = this;
me.records = [];
this.clearAll = true;
let session = this.driver.session();
if (query == "") return;
session.run(query, {}).then((result) => {
me.clearAll = false;
me.records = result.records;
console.log("neo4j 查詢結(jié)果", result.records);
session.close();
me.closeLoading(false);
}).catch(function (error) {
console.log("Cypher 執(zhí)行失敗!", error);
me.driver.close();
});
},
closeLoading(status) {
console.log('closeLoading', status);
},
以上我們就查詢到了數(shù)據(jù),緊接著開(kāi)始處理數(shù)據(jù),首先處理成適用echarts的數(shù)據(jù)格式
2、使用echarts繪圖
首先處理獲取的數(shù)據(jù)
/**
* 直接執(zhí)行Cypher
*/
executeCypher(query) {
this.echartsNode = [] //節(jié)點(diǎn)數(shù)組
this.nodesRelation = [] //關(guān)系線數(shù)組
this.category = [] //echarts圖例數(shù)據(jù)數(shù)
// 創(chuàng)建實(shí)例
this.driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', '******'));
console.log("?? ~ file: AuthorArticleSearch.vue ~ line 46 ~ mounted ~ this.drive", this.driver)
let me = this;
me.records = [];
this.clearAll = true;
let session = this.driver.session();
if (query == "") return;
session.run(query, {}).then((result) => {
me.clearAll = false;
me.records = result.records;
console.log("neo4j 查詢結(jié)果", result.records);
// 開(kāi)始處理數(shù)據(jù)
for (let i = 0; i < me.records.length; i++) {
this.echartsData.push({
name: me.records[i]._fields[0].segments[0].start.properties.name,
category: me.records[i]._fields[0].segments[0].start.labels[0]
});
this.echartsData.push({
name: me.records[i]._fields[0].segments[0].end.properties.name,
category: me.records[i]._fields[0].segments[0].end.labels[0]
});
this.nodesRelation.push({
source: me.records[i]._fields[0].segments[0].start.properties.name,
target: me.records[i]._fields[0].segments[0].end.properties.name,
name: me.records[i]._fields[0].segments[0].relationship.type,
});
}
//刪除arr中的重復(fù)對(duì)象
var arrId = [];
var legend = [];
for (var item of this.echartsData) {
legend.push({ name: item.category })
if (arrId.indexOf(item.name) == -1) {
arrId.push(item.name)
this.echartsNode.push(item);
}
}
this.category = Array.from(new Set(legend))
session.close();
me.closeLoading(false);
}).catch(function (error) {
console.log("Cypher 執(zhí)行失敗!", error);
me.driver.close();
});
setTimeout(() => {
this.knowlegGraphshow = true
}, 4000);
},
closeLoading(status) {
console.log('closeLoading', status);
},
echarts配置:
this.options = {
tooltip: {//彈窗
show: false,
// enterable: true,//鼠標(biāo)是否可進(jìn)入提示框浮層中
// formatter: formatterHover,//修改鼠標(biāo)懸停顯示的內(nèi)容
},
legend: {
type: 'scroll',
orient: 'vertical',
left: 10,
top: 20,
bottom: 20,
data: this.category
},
series: [
{
categories: this.category,
// categories: [{
// name: "籌資渠道"
// }],
type: "graph",
layout: "force",
zoom: 0.6,
symbolSize: 60,
// 節(jié)點(diǎn)是否可以拖動(dòng)
draggable: true,
roam: true,
hoverAnimation: false,
// labelLayout: {
// hideOverlap: true,
// },
legendHoverLink: false,
nodeScaleRatio: 0.6, //鼠標(biāo)漫游縮放時(shí)節(jié)點(diǎn)的相應(yīng)縮放比例,當(dāng)設(shè)為0時(shí)節(jié)點(diǎn)不隨著鼠標(biāo)的縮放而縮放
focusNodeAdjacency: false, //是否在鼠標(biāo)移到節(jié)點(diǎn)上的時(shí)候突出顯示節(jié)點(diǎn)以及節(jié)點(diǎn)的邊和鄰接節(jié)點(diǎn)。
// categories: categories,
itemStyle: {
color: "#67A3FF",
},
edgeSymbol: ["", "arrow"],
// edgeSymbolSize: [80, 10],
edgeLabel: {
normal: {
show: true,
textStyle: {
fontSize: 12,
},
formatter(x) {
return x.data.name;
},
},
},
label: {
normal: {
show: true,
textStyle: {
fontSize: 12,
},
color: "#f6f6f6",
textBorderColor: '#67A3FF',
textBorderWidth: '1.3',
// 多字換行
formatter: function (params) {
// console.log(params);
var newParamsName = "";
var paramsNameNumber = params.name.length;
var provideNumber = 7; //一行顯示幾個(gè)字
var rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (var p = 0; p < rowNumber; p++) {
var tempStr = "";
var start = p * provideNumber;
var end = start + provideNumber;
if (p == rowNumber - 1) {
tempStr = params.name.substring(start, paramsNameNumber);
} else {
tempStr = params.name.substring(start, end) + "\n\n";
}
newParamsName += tempStr;
}
} else {
newParamsName = params.name;
}
return newParamsName;
},
},
},
force: {
repulsion: 200, // 節(jié)點(diǎn)之間的斥力因子。支持?jǐn)?shù)組表達(dá)斥力范圍,值越大斥力越大。
gravity: 0.01, // 節(jié)點(diǎn)受到的向中心的引力因子。該值越大節(jié)點(diǎn)越往中心點(diǎn)靠攏。
edgeLength: 400, // 邊的兩個(gè)節(jié)點(diǎn)之間的距離,這個(gè)距離也會(huì)受 repulsion影響 。值越大則長(zhǎng)度越長(zhǎng)
layoutAnimation: true, // 因?yàn)榱σ龑?dǎo)布局會(huì)在多次迭代后才會(huì)穩(wěn)定,這個(gè)參數(shù)決定是否顯示布局的迭代動(dòng)畫
// 在瀏覽器端節(jié)點(diǎn)數(shù)據(jù)較多(>100)的時(shí)候不建議關(guān)閉,布局過(guò)程會(huì)造成瀏覽器假死。
},
data: this.data,
links: this.links,
// categories: this.categories
}
]
}
3、使用vis.js繪圖
下載依賴:
npm install -s vis,js
引入:
//import Vis from "vis";
const Vis = require('vis-network/dist/vis-network.min');
require('vis-network/dist/dist/vis-network.min.css');
首先處理數(shù)據(jù):
在這里插入代碼片
/**
* 直接執(zhí)行Cypher
*/
executeCypher(query) {
this.echartsNode = [] //節(jié)點(diǎn)數(shù)組
this.nodesRelation = [] //關(guān)系線數(shù)組
// 創(chuàng)建實(shí)例
this.driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'KG****'));
console.log("?? ~ file: AuthorArticleSearch.vue ~ line 46 ~ mounted ~ this.drive", this.driver)
let me = this;
me.records = [];
this.clearAll = true;
let session = this.driver.session();
if (query == "") return;
session.run(query, {}).then((result) => {
me.clearAll = false;
me.records = result.records;
console.log("neo4j 查詢結(jié)果", result.records);
// 開(kāi)始處理數(shù)據(jù)
let nodes = new Set();
for (let i = 0; i < me.records.length; i++) {
nodes.add(me.records[i]._fields[0].segments[0].start.properties.name);
nodes.add(me.records[i]._fields[0].segments[0].end.properties.name);
this.nodesRelation.push({
from: me.records[i]._fields[0].segments[0].start.properties.name,
to: me.records[i]._fields[0].segments[0].end.properties.name,
label: me.records[i]._fields[0].segments[0].relationship.type,
id: i,
});
}
nodes.forEach((e) => {
this.echartsData.push({
label: e,
id: e,
});
})
session.close();
me.closeLoading(false);
}).catch(function (error) {
console.log("Cypher 執(zhí)行失敗!", error);
me.driver.close();
});
this.nodesArray = this.echartsData //節(jié)點(diǎn)數(shù)組
this.edgesArray = this.nodesRelation //關(guān)系線數(shù)組
setTimeout(() => {
this.knowlegGraphshow = true
}, 4000);
},
closeLoading(status) {
console.log('closeLoading', status);
},
定義繪圖dom元素
// width,height 畫布的寬度,高度。 可以是百分比或像素,一般在dom元素上設(shè)置 -->
<div v-if="knowlegGraphshow == true" id="network_id" ref="network_id" class="network" style="height: 100%;">
</div>
調(diào)用繪圖方法:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-785780.html
// vis.js畫圖
visDraw() {
let container = this.$refs.network_id;
let data = { nodes: this.nodesArray, edges: this.edgesArray }
console.log("?? ~ file: pageKnowlegGraph.vue ~ line 135 ~ visDraw ~ data", data)
let options = {
autoResize: true,
// / 設(shè)置節(jié)點(diǎn)樣式
nodes: {
shape: "dot",
size: 20,
font: {
//字體配置
size: 20
},
color: {
// border: "#2B7CE9", //節(jié)點(diǎn)邊框顏色
background: "#97C2FC", //節(jié)點(diǎn)背景顏色
highlight: {
//節(jié)點(diǎn)選中時(shí)狀態(tài)顏色
border: "#2B7CE9",
background: "#D2E5FF"
},
hover: {
//節(jié)點(diǎn)鼠標(biāo)滑過(guò)時(shí)狀態(tài)顏色
border: "#2B7CE9",
background: "#D2E5FF"
}
},
borderWidth: 0, //節(jié)點(diǎn)邊框?qū)挾?,單位為px
borderWidthSelected: 2 //節(jié)點(diǎn)被選中時(shí)邊框的寬度,單位為px
},
// 邊線配置
edges: {
width: 1,
length: 260,
color: {
color: "#848484",
highlight: "#848484",
hover: "#848484",
inherit: "from",
opacity: 1.0
},
shadow: false,
smooth: {
//設(shè)置兩個(gè)節(jié)點(diǎn)之前的連線的狀態(tài)
enabled: false //默認(rèn)是true,設(shè)置為false之后,兩個(gè)節(jié)點(diǎn)之前的連線始終為直線,不會(huì)出現(xiàn)貝塞爾曲線
},
arrows: { to: true } //箭頭指向to
},
//計(jì)算節(jié)點(diǎn)之前斥力,進(jìn)行自動(dòng)排列的屬性
physics: {
// enabled: true, //默認(rèn)是true,設(shè)置為false后,節(jié)點(diǎn)將不會(huì)自動(dòng)改變,拖動(dòng)誰(shuí)誰(shuí)動(dòng)。不影響其他的節(jié)點(diǎn)
// barnesHut: {
// gravitationalConstant: -4000,
// centralGravity: 0.3,
// springLength: 120,
// springConstant: 0.04,
// damping: 0.09,
// avoidOverlap: 0
// },
},
// physics: false,
//用于所有用戶與網(wǎng)絡(luò)的交互。處理鼠標(biāo)和觸摸事件以及導(dǎo)航按鈕和彈出窗口
interaction: {
hover: true,
dragNodes: true, //是否能拖動(dòng)節(jié)點(diǎn)
dragView: true, //是否能拖動(dòng)畫布
// hover: true, //鼠標(biāo)移過(guò)后加粗該節(jié)點(diǎn)和連接線
// multiselect: true, //按 ctrl 多選
// selectable: true, //是否可以點(diǎn)擊選擇
// selectConnectedEdges: true, //選擇節(jié)點(diǎn)后是否顯示連接線
// hoverConnectedEdges: true, //鼠標(biāo)滑動(dòng)節(jié)點(diǎn)后是否顯示連接線
zoomView: true //是否能縮放畫布
},
};
this.network = new Vis.Network(container, data, options);
},
源碼已上傳,需要的小伙伴可前往主頁(yè)找到下載,https://download.csdn.net/download/qq_41859063/86246454?spm=1001.2014.3001.5503。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-785780.html
到了這里,關(guān)于vue+neo4j +純前端(neovis.js / neo4j-driver) 實(shí)現(xiàn) 知識(shí)圖譜的集成 大干貨--踩坑無(wú)數(shù)?。?!將經(jīng)驗(yàn)分享給有需要的小伙伴的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!