preface

Used to go nuggets, are white piao other people’s posts, what will not check what.

Today, I routinely went to a white prostitute. I searched small demo related to neo4j visualization on the Internet. I went to a prostitute and found my conscience and my thoughts were like diabetes insipidus.

Maybe I’ll write something, too! Well, that’s settled.

A load of crap

The original intention is that part of the graduation project involves the front-end visualization of Neo4j. How can I do that? It’s okay, you fucking bitch!

I looked on the Internet, the feasible plan is really many! D3, Echarts, G6, etc. Choose to choose, like TM pick concubine, cross-stitch eye……

Unfortunately, just saw a post, the name I have forgotten, sorry brother. He used Echarts to achieve, so, after a close look, found that the implementation of the idea is quite simple, the whole process of the code is not complicated. Well, then it’s you! Wonderful! Frog! Kind of! The child! . Sorry, Echarts (smiling face 🙂)

Phase 1

I wonder how to visualize nodes and edges like neo4j into the front page? Well, I’ll build it! Let’s make some data.

This is my node data: yes, you read that right, just like Marvel ~

[{"name": Avengers 3."category": 0."id": 0 },
        { "name": Captain America."category": 0."id": 1 },
        { "name": "Anthony Russell."."category": 3."id": 2 },
        { "name": "Science fiction"."category": 2."id": 3 },
        { "name": "The plot"."category": 2."id": 4 },
        { "name": "Chris Evan."."category": 1."id": 5 },
        { "name": "Scarlett Johansson."."category": 1."id": 6}]Copy the code

Here is the built relational data:

[{"source": 0."target": 2."category": 0."value": "Director"."symbolSize": 5 },
    { "source": 1."target": 2."category": 0."value": "Director"."symbolSize": 5 },
    { "source": 0."target": 3."category": 0."value": "Type"."symbolSize": 5 },
    { "source": 1."target": 3."category": 0."value": "Type"."symbolSize": 5 },
    { "source": 0."target": 4."category": 0."value": "Type"."symbolSize": 5 },
    { "source": 1."target": 4."category": 0."value": "Type"."symbolSize": 5 },
    { "source": 0."target": 5."category": 0."value": "Star"."symbolSize": 5 },
    { "source": 1."target": 5."category": 0."value": "Star"."symbolSize": 5 },
    { "source": 2."target": 5."category": 0."value": "Friends"."symbolSize": 5 },
    { "source": 5."target": 2."category": 0."value": ""."symbolSize": 5 },
    { "source": 0."target": 6."category": 0."value": "Star"."symbolSize": 5 },
    { "source": 1."target": 6."category": 0."value": "Star"."symbolSize": 5 },
    { "source": 2."target": 6."category": 0."value": "Friends"."symbolSize": 5 },
    { "source": 6."target": 2."category": 0."value": ""."symbolSize": 5 },
    { "source": 5."target": 6."category": 0."value": "Friends"."symbolSize": 5 },
    { "source": 6."target": 5."category": 0."value": ""."symbolSize": 5}]Copy the code

I wipe! It’s not human to create data. I’m tired of both of them…

I saw a code in the process of white prostitution, which is now to be mentioned in stage 1, as follows:

// An array of paths to the file to read
            const urls = ['./node.json'.'./links.json'];
            const doSth = async() = > {const results = await Promise.all(urls.map(url= > fetch(url).then(response= > response.json())));

            // promise.all returns an array of all successful results
            let mydata = results[0];
            let links = results[1];

            // Get the DOM of the echarts to be manipulated
            var myChart = echarts.init(document.getElementById('graph'));

            // The configuration item of the atlas
            option = {
                // Configure the prompt box
                tooltip: {
                    formatter: x= > {
                        return [x.data.name];// Set the content and format of the prompt box to display the name property on both nodes and sides}},animationDurationUpdate: 5000.animationEasingUpdate: 'quarticlnOut'.// quarticlnOut quinticInOut

                // A text label on a graph, which can be used to describe some data information about the graph
                label: {
                    show: true.textStyle: {
                        fontSize: 12}},legend: {
                    x: "center".show: true
                },
                series: [{type: 'graph'.// Type: diagram
                        layout: 'force'.// Map layout, type and map mapping
                        symbolSize: 65.// Node size
                        focusNodeAdjacency: true.// When the mouse moves over the node, highlight the node and its edges and adjacent nodes
                        draggable: true.// Indicates whether the node can be dragged
                        roam: true.edgeSymbol: ['none'.'arrow'].categories: [{
                            name: 'movie'.itemStyle: {
                                color: "lightgreen"}}, {name: 'star'.itemStyle: {
                                color: "orange",}}, {name: 'type'.itemStyle: {
                                color: "pink",}}, {name: 'director'.color: "lightblue",}],label: {
                            show: true.textStyle: {
                                fontSize: 12.color: "black",}},force: {
                            repulsion: 4000.// Repulsive factor between nodes. Arrays are supported to express the range of repulsion, the larger the value, the greater the repulsion.
                            edgeLength: 80.// The distance between two nodes of an edge
                            gravity: 0.1.// The node is subjected to the gravity factor toward the center. The larger the value is, the closer the node is to the center.
                        },
                        edgeSymbolSize: [4.50].// The size of the tags on both sides of an edge can be an array, or a single, uniform size.
                        edgeLabel: {
                            show: true.textStyle: {
                                fontSize: 10
                            },
                            formatter: "{c}"
                        },
                        data: mydata,
                        links: links,
                        lineStyle: {
                            opacity: 0.9.width: 1.1.curveness: 0.color: "# 262626",}}]};// Display the chart using the configuration items and data you just specified.
            myChart.setOption(option);
        }
        doSth();
Copy the code

This code basically means that I can request access to the data in the two files I created, instantiate Echarts, configure Echarts options, and draw the nodes and edges I created into the DOM.

It looks pretty good, but the results are actually pretty good. The bird food is already visible on the page, but it’s ugly. The renderings are as follows:

But the annoying thing is that I can’t drag a node in the diagram to stay anywhere. This is boring ah! Always a ghost look, look uncomfortable.

And then, it’s another routine hooker. Saw a custom location code, hurriedly piao come to try! True CV engineer (-_-)…

The code might look something like this:

            // Node custom drag does not bounce back
            myChart.on('mouseup'.function (params) {
                var op = myChart.getOption();
                op.series[0].data[params.dataIndex].x = params.event.offsetX;
                op.series[0].data[params.dataIndex].y = params.event.offsetY;
                op.series[0].data[params.dataIndex].fixed = true;
                myChart.setOption(op);
            });
Copy the code

Better! You can drag it into any shape you want, lol.

The stage 2

I thought I can’t always build my own nodes, can I? One or two is easy, this data set can be thousands of nodes, tens of thousands of relationships (yes, THE data set I am looking for is TMDb5000, is very small…). How long will it take to build this by yourself?

Yes, let me show you the data scale in my neo4j graph database. It’s not like I can make it myself.

Well, try using JS to access neo4j.

Whoosh, whoosh, spring is here. Oh, no! Code found! It looks something like this:

var request = require("request");
var host = 'localhost',
    port = 7474;
var httpUrlForTransaction = 'http://' + host + ':' + port + '/db/data/transaction/commit';

function runCypherQuery(query, params, callback) {
    request.post({
        uri: httpUrlForTransaction,
        json: { statements: [{ statement: query, parameters: params }] }
    },
        function (err, res, body) {
            callback(err, body);
        })
}

runCypherQuery(
    'MATCH (m:Movie { title: $name}) RETURN m', {
    name: 'Hulk'
}, function (err, resp) {
    if (err) {
        console.log(err);
    } else {
        console.log(resp.results[0].data[0]); }});Copy the code

The above code roughly means that, first connect to the local neo4j database through URL, then write Cypher in JS, then send request for query, and then get the request result for processing, which is stage 2 here.

Look at the result, query under the Hulk (Hulk), in node, the result is not there!

Hulk node found successfully!

But how do I visualize the data I’ve found? The format of what is also different ah?

This is stage 3!

Phase 3

Since the query result in stage 2 is not the same as the format of nodes and relationships in stage 1, it should be changed to the same. Something ~

But since the previous testing work done, then turned the Vue directly, in fact, the main content about the same, is slightly the request to the data into a format they want, all talk accusers, then directly on code (PS: but what CSS more write more disorderly, simply whether it, just follow, vexed!) :

<script> export default {data() {return {input: ", // movieName: ", // movieName: ", // DirectorList: ", // Movie Demo Movie type genresList: ", // Movie demo movie type genresList: EchartsRelation: [], // The following five are parameters to connect to the database of neo4j: protocol: 'neo4j', host: 'localhost', port: 7687, username: 'neo4j', password: 'neo4j', If (this.mychart) {this.configgraph (p1, p2); if(this.mychart) {this.configgraph (p1, p2); }else {this.mychart = this.echarts.init (this.$refs.graph); this.configGraph(p1, p2); Return this.$neo4j.connect(this.protocol, this.host, this.port, this.username, This.password)}, // query the searchGraph() {// Connect to the database this.connect(); This. actorList = ''; // Clear the contents of the movie display before searching. this.directorList = ''; this.idList = ''; this.genresList = ''; this.movieName = ''; this.echartsData = []; this.echartsRelation = []; this.movieName = this.input; Const session = this.$neo4j.getSession() returns a Promise session.run(' MATCH ') (m:Movie{title:'${this.movieName}'}) -->(n) RETURN m,n`) .then(res => { let records = res.records; If (records.length == 0) {this.$message.warning(" The movie you are searching for does not exist in the dataset!" ); }else {this.echartsData.push({name: '${this.moviename}', category: 0}); for (let i = 0; i < records.length; I ++) {if(records[I]._fields[1].properties.name) {if(records[I]._fields[1].labels[0] == 'Actor') {if(records[I]._fields[1].labels[0] == 'Actor') { this.actorList += records[i]._fields[1].properties.name + ', '; this.echartsData.push({ name: records[i]._fields[1].properties.name, category: 1}); this.echartsRelation.push({ source: records[i]._fields[0].properties.title, target: records[i]._fields[1].properties.name, value: records[i]._fields[1].labels[0]}); }else {// Save the director node and relation this.directorList += Records [I]._fields[1].properties. Name; this.echartsData.push({ name: records[i]._fields[1].properties.name, category: 3}); this.echartsRelation.push({ source: records[i]._fields[0].properties.title, target: records[i]._fields[1].properties.name, value: records[i]._fields[1].labels[0]}); }}else if(Records [I]._fields[1].properties. Id) {this.idList += Records [I]._fields[1].properties. Id; this.echartsData.push({ name: records[i]._fields[1].properties.id, category: 4}); this.echartsRelation.push({ source: records[i]._fields[0].properties.title, target: records[i]._fields[1].properties.id, value: records[i]._fields[1].labels[0]}); }else {this.genresList += Records [I]._fields[1].properties. Title + ', '; this.echartsData.push({ name: records[i]._fields[1].properties.title, category: 2}); this.echartsRelation.push({ source: records[i]._fields[0].properties.title, target: records[i]._fields[1].properties.title, value: records[i]._fields[1].labels[0]}); GetGraph (this.echartsData, this.echartsrelation); }). Then (() => {session.close()})}, // configGraph(p1, p2) { let links = p2; // Map configuration item let option = {// tooltip: {trigger: Label: {fontSize: 12}, legend: {x: "center", show: {fontSize: 12}, legend: {x: "center", show: True}, series: [{type: 'graph',// type: layout: 'force',// Type: layout: 'force',// Type: layout: 'force',// Type: layout: 'force',// Type: layout: 'force',// 'Adjacency'},// When the mouse mouse moves over the node, highlight the node and its edges and adjacent nodes draggable: true,// Indicate whether the node can be dragged: true,// Categories: [{name: 'movie ', itemStyle: {color: "lightgreen"}}, {name: "lightgreen"} ItemStyle: {color: "pink",}}, {name: 'type ', itemStyle: {color: "pink",}}, {name:' director ', itemStyle: {color: "pink",}}, {name: 'director ', itemStyle: {color: "pink",}} {color: "lightblue",}},{name: 'TMDbID', itemStyle: {color: "#fcce4c",}}], True, fontSize: 12, color: "black",}, force: {repulsion: 1200,// Repulsive force factor between nodes. }, edgeSymbolSize: 0.1, // The gravity factor towards the center of the node. // edgeLabel: {show: true, fontSize: 12, formatter: {show: true, fontSize: 12, formatter: Opacity: 0, opacity: 0, opacity: 0, opacity: 0, opacity: 0, opacity: 0, opacity: 0 0, color: "#262626", } } ] }; // const chart = this.mychart; chart.on('mouseup', function (params) { var option = chart.getOption(); option.series[0].data[params.dataIndex].x = params.event.offsetX; option.series[0].data[params.dataIndex].y = params.event.offsetY; option.series[0].data[params.dataIndex].fixed = true; chart.setOption(option); }); // Display the chart using the configuration items and data you just specified. this.myChart.setOption(option); }, } } </script>Copy the code

The above code basically means that when the query button is clicked, the searchGraph event will be triggered. In the searchGraph function, the URL will be connected to the local neo4j database by calling the connect function. Then, as in stage 2, Cypher will be written in JS. Then send the request for query, and then take the request result for processing, and draw the knowledge graph, which is the stage 3 here.

Take a look at the effect

Above is the relevant information about “Hulk” that I queried in the neo4j database.

Wouldn’t it be great to use the same method to search for the movie you want to know in the search box above?

Of course, you can also configure Echarts plugin to use different functions in the movie Graph relationship display, such as highlighting, clicking on the corresponding color box to display only the corresponding color, hovering over nodes and edges to display information, and so on.

So Echarts is very powerful. (Hee hee hee)

PS: In fact, I have seen other similar libraries that can easily implement similar functionality. For example, the G6 mentioned earlier can also be ~

conclusion

Good, said so much, already not quite accord with own disposition, but disposition this thing who say of accurate, habit white whoring of I, perhaps today is want to write down, perhaps tomorrow don’t want to write again.

So while today’s own, hurriedly write out these things hair, I am afraid I will not be too lazy to write…. tomorrow (🙂 🙂 🙂)

Goodbye, everyone