Создание визуализаций данных с помощью Express и получение данных из базы данных PostgreSQL
Я создаю узел.приложение js, которое очищает некоторую информацию из интернета и сохраняет эту информацию в базе данных postgreSQL.
Теперь я хотел бы создать некоторые визуализации с помощью D3.js.
Обычно я создаю визуализации с помощью .csv
файл, но теперь я хотел бы получить данные из моей базы данных.
Я думаю, что использовать Express.js
.
Это мой код, он работает, но он принимает данные из .csv
файл, не из децибел.
app.js:
const express = require('express');
var app = express();
const start = async function() {
console.log('n(1) Connect to db');
await postgreSQLlib.connect();
console.log('n(02) Create tables if they do not exist');
await postgreSQLlib.createTables();
console.log('n(03) Check if table 'example' is updated or not');
if(!await utilFunc.isTableUpdated('example', 6308)) {
console.log('n (04) Download data for coverages');
await downloader.download();
console.log('n (05) Elaborate data for example before to save on DB');
await elaborate.elaborate();
console.log('n (06) Saving data on db');
await saveOnDb.save();
}
console.log('n(10) D3js visualizations');
app.set('port', process.env.PORT || 300)
var server = app.listen(app.get('port'), function() {
console.log('Listening on PORT: ' + app.get('port'));
});
app.use('/',express.static('public/donut'))
// I can't disconnect from db if I have to show visualizations, am I right?
console.log('n(11) Disconnect');
await postgreSQLlib.disconnect();
}
start()
.then(function(res) {
console.log('Done');
})
.catch(function(err) {
console.log(err);
});
.HTML-код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Donut</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="./donut.css" media="screen"/>
</head>
<body>
<script src="./donut.js"></script>
</body>
</html>
Донат.js:
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 70);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("./data.csv", type, function(error, data) {
if (error) throw error;
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.data.age; });
});
function type(d) {
d.population = +d.population;
return d;
}
данные.csv:
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
я тоже пытаюсь:
const start = async function() {
//...
function onRequest(req, res) {
if(req.method == 'GET' && req.url == '/') {
var client = new pg.Client(conString);
client.connect();
var query = client.query('SELECT * FROM example;');
query.on('row', function(row, result) {
result.addRow(row);
});
query.on('end', function(result) {
res.status(200)
res.json(result.rows);
client.end();
});
}
}
}
и:
d3.csv("/", type, function(error, data) {
if(error) {
throw error;
}
console.log('data:', data);
...
}
но это не работает.
Я бы не использовал .файл CSV для хранения моих данных, но я хочу использовать БД. Как я могу это сделать?
2 ответов
мое решение требует установки двух дополнительных модулей:
npm install -save express-handlebars
& npm install -save pg-promise
после этого в app.js
вы можете подключиться к вашему серверу postgresql и проанализировать данные через помощников руля, вот весь код для этого.
app.js
const express = require('express');
const exphbs = require('express-handlebars');
const pgp = require('pg-promise')(/*options*/);
var app = express();
dbLoad();
function dbLoad() {
var connect = {
host: 'localhost',
port: 5432,
database: 'postgres',
user: 'postgres',
password: 'YourPassword'
};
var db = pgp(connect);
db.query({
text: 'SELECT * FROM table1',
values: [],
rowMode: 'array'
})
.then(data => {
var arr = [];
data.forEach(function(d) {
var i = 0
arr.push({
age: d[i],
population: d[i + 1]
})
i++
})
pageLoad(arr); // Function call to load the page
})
.catch(reason => {
console.log(reason)
});
}
function pageLoad(data) {
var hbs = exphbs.create({
helpers: {
sqlData: function () { return JSON.stringify(data); }
}
});
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.get('/', function (req, res, next) {
res.render('home', {
showTitle: true,
});
});
app.listen(3000);
}
это предполагает, что у вас есть данные на вашем сервере под названием table1 с точно такой же структурой данных, как ваш csv.
затем вы должны создать папка под названием вид в той же папке, что app.js
и создайте файл с именем home.handlebars
(это замена для вашего index.html
)
в этом файле вы захотите вызвать свои данные так {{sqlData}} и проанализировать их.
дома.руль!--17-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="//d3js.org/d3.v3.min.js"></script>
<title></title>
</head>
<body>
<div id="chart"></div>
</body>
<script>
var init = JSON.parse("{{sqlData}}".replace(/"/g,'"').replace(/</,''))
chart(init);
function chart(data) {
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 70);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.data.age; });
}
</script>
</html>
и это должно быть так.
Примечание я не эксперт в узле.js и может быть какой-то серьезный недостаток безопасности, делая это таким образом, если вы обеспокоенный этим, я бы предложил пойти через экспресс.С. API и просмотрите правильный способ получить объект json непосредственно из приложения.js без всей замены hacky string, которую я сделал в этом решении.
EDIT:
уменьшил stringreplacement до одной строки кода:
var init = JSON.parse("{{sqlData}}".replace(/"/g,'"').replace(/</,''))
оберните свой код d3 в функцию, которая вызывается всякий раз, когда вы извлекли свои данные как json курьерским.js call donut (json) like
Донат.js:
function donut(json) {
...
var g = svg.selectAll(".arc")
.data(pie(json))
.enter().append("g")
.attr("class", "arc");
...
}
или использовать d3.в JSON чтобы получить json с сервера и передать URL-адрес как
...
d3.json(data_url, type, function(error, data) {
if (error) throw error;
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
...