Last active
August 30, 2018 22:45
-
-
Save jexp/f4ae19be0e06d8a19867f294e09f0759 to your computer and use it in GitHub Desktop.
Charting Neo4j Cypher Results and Database Statistics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- License MIT --> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Neo4j Charts</title> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" | |
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" | |
integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous"> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" | |
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" | |
crossorigin="anonymous"></script> | |
<script type="text/javascript" | |
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.bundle.min.js"></script> | |
<script src="https://cdn.rawgit.com/neo4j/neo4j-javascript-driver/1.1/lib/browser/neo4j-web.min.js"></script> | |
<script type="text/javascript"> | |
var samples = 10; | |
var statsChart, queryChart; | |
function newStatsChart() { | |
// tag::chart-setup[] | |
return new Chart($("#statsChart"), { | |
label: 'Neo4j Database Statistics', | |
type: 'line', height: 1000, width: 800, | |
fill: false, lineTension: 0, showLines: true, | |
data: { labels: [], datasets: [] }, | |
options: { | |
scales: { | |
xAxes: [{ | |
type: 'time', time: {unit: 'second', displayFormats: {second: "HH:mm:ss"}}, | |
ticks: { callback: function (label, index) { return index % 2 == 0 ? label : "" } } | |
}], | |
yAxes: [{ | |
type: 'logarithmic', min: 0, | |
ticks: { callback: function (label) { return label; } } // no scientific notation | |
}] | |
} | |
} | |
}); | |
// end::chart-setup[] | |
} | |
$(document).ready(function () { | |
statsChart = newStatsChart(); | |
statsChart.update(); | |
queryChart = new Chart($("#queryChart"), { | |
type: 'line', label: 'Query Results', fill: false, lineTension: 0, showLines: true, | |
data: {labels: [], datasets: []} | |
}); | |
queryChart.update(); | |
}); | |
var running = undefined; | |
function toggle() { | |
if (!running) { | |
running = setInterval(stats, parseInt($("#refresh").val()) * 1000); | |
stats(); | |
stats(); | |
$("#stats").text("Stats: Stop"); | |
} else { | |
clearInterval(running); | |
running = undefined; | |
$("#stats").text("Stats: Start"); | |
} | |
} | |
// tag::stats-query[] | |
function stats() { | |
var neo = neo4j.v1; | |
var driver = neo.driver($("#url").val(), neo.auth.basic("neo4j", $("#password").val())); | |
var session = driver.session(); | |
var session2 = driver.session(); | |
var d = Date.now(); | |
session2.run("MATCH () RETURN count(*)").then(function (result) { | |
update(d, "nodes", result.records[0]._fields[0].toNumber()); | |
}); | |
session2.run("MATCH ()-->() RETURN count(*)").then(function (result) { | |
update(d, "rels", result.records[0]._fields[0].toNumber()); | |
}); | |
session.run("CALL db.labels()").then(function (result) { | |
result.records.forEach(function (r) { | |
var l = r._fields[0]; | |
var stmt = "MATCH (:`" + l + "`) RETURN count(*)"; | |
session2.run(stmt).then(function (result2) { | |
update(d, l, result2.records[0]._fields[0].toNumber()); | |
}); | |
}); | |
}); | |
session.run("CALL db.relationshipTypes()").then(function (result) { | |
result.records.forEach(function (r) { | |
var l = r._fields[0]; | |
var stmt = "MATCH ()-[:`" + l + "`]->() RETURN count(*)"; | |
session2.run(stmt).then(function (result2) { | |
update(d, l, result2.records[0]._fields[0].toNumber()); | |
}); | |
}); | |
}); | |
} | |
// end::stats-query[] | |
// tag::chart-update[] | |
// from http://colorbrewer2.org/ via http://www.zingchart.com/blog/2015/12/09/color-charts/ | |
var colors = ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd']; | |
function update(time, label, value) { | |
var labels = statsChart.data.labels; | |
var datasets = statsChart.data.datasets; | |
var title = "# of " + label; | |
var insert = labels.indexOf(time); | |
// new timestamp | |
if (insert == -1) { | |
// too many samples, remove first entry | |
if (labels.length > samples) { | |
labels.shift(); | |
datasets.forEach(function (ds) { ds.data.shift(); }); | |
} | |
insert = labels.length; | |
labels[insert] = time; | |
} | |
// find dataset | |
var idx = datasets.findIndex(function(ds) { return ds.label == title}); | |
// add new dataset | |
if (idx == -1) { | |
idx = datasets.length; | |
datasets.push({ label: title, data: labels.map(function(){return 1;}), borderColor: colors[idx % colors.length], fill: false}); | |
} | |
datasets[idx].data[insert] = value; | |
statsChart.update(); | |
} | |
// end::chart-update[] | |
function query() { | |
var neo = neo4j.v1; | |
var driver = neo.driver($("#url").val(), neo.auth.basic("neo4j", $("#password").val())); | |
var session = driver.session(); | |
session.run($("#query").val()).then(function (result) { | |
var data = queryChart.data; | |
var first = true; | |
data.labels = []; | |
result.records.forEach(function (r) { | |
if (data.labels.length == 0) { | |
queryChart.label = 'Query Results' + r.keys[0]; | |
for (var i = 1; i < r.keys.length; i++) { | |
data.datasets[i - 1] = { | |
label: r.keys[i], | |
data: [], | |
fill: false, | |
borderColor: colors[i % colors.length] | |
}; | |
} | |
} | |
var l = r._fields[0].toString(); | |
data.labels.push(l); | |
for (var i = 1; i < r._fields.length; i++) { | |
var v = r._fields[i].toNumber ? r._fields[i].toNumber() : r._fields[i]; | |
data.datasets[i - 1].data.push(v); | |
} | |
}); | |
queryChart.update(1000, true); | |
session.close(); | |
driver.close(); | |
}); | |
} | |
</script> | |
</head> | |
<body> | |
<nav class="navbar navbar-inverse navbar-fixed-top"> | |
<div class="container"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" | |
aria-expanded="false" aria-controls="navbar"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
</button> | |
<a class="navbar-brand" href="#">Neo4j Charts</a> | |
</div> | |
<div id="navbar" class="navbar-collapse collapse"> | |
<form class="navbar-form navbar-left"> | |
<div class="form-group"> | |
<input type="text" id="url" value="bolt://localhost" class="form-control"> | |
</div> | |
<div class="form-group"> | |
<input type="password" id="password" value="test" class="form-control"> | |
</div> | |
<div class="form-group"> | |
<input type="number" id="refresh" value="60" title="Refresh in seconds" class="form-control"> | |
</div> | |
<button id="stats" class="btn btn-success" onclick="toggle();return false;">Stats: Start</button> | |
</form> | |
</div><!--/.navbar-collapse --> | |
</div> | |
</nav> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-6"> | |
<h2>Database Statistics</h2> | |
<canvas id="statsChart" height="400"></canvas> | |
</div> | |
<div class="col-md-6"> | |
<h2>Render your own results</h2> | |
<canvas id="queryChart"></canvas> | |
<div class="row"> | |
<div class="col-md-11"> | |
<textarea id="query" cols="70" rows="4">MATCH (n) | |
RETURN labels(n), count(*)</textarea> | |
</div> | |
<div class="col-md-1"> | |
<button class="btn btn-success" onClick="query()">Run</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<footer> | |
<p>Built using the <a target="_blank" href="http://github.com/neo4j/neo4j-javascript-driver">Neo4j Javascript | |
Driver</a> and <a target="_blank" href="http://chartjs.org">Chart.js</a>. <a | |
href="https://gist.github.com/jexp/f4ae19be0e06d8a19867f294e09f0759" target="_blank">Source Code on | |
GitHub</a></p> | |
</footer> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment