Node.js 使用Express创建数据可视化并从PostgreSQL数据库获取数据
我构建了一个Node.js应用程序,它可以从互联网上获取一些信息,并将这些信息保存在postgreSQL数据库中。 现在我想使用D3.js创建一些可视化。 通常我使用Node.js 使用Express创建数据可视化并从PostgreSQL数据库获取数据,node.js,postgresql,express,d3.js,Node.js,Postgresql,Express,D3.js,我构建了一个Node.js应用程序,它可以从互联网上获取一些信息,并将这些信息保存在postgreSQL数据库中。 现在我想使用D3.js创建一些可视化。 通常我使用.csv文件创建可视化,但现在我想从数据库中获取数据 我想使用Express.js。 这是我的代码,它可以工作,但它从.csv文件中获取数据,而不是从数据库中获取数据 app.js: const express = require('express'); var app = express(); const start = asy
.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);
});
<!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>
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;
}
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
function donut(json) {
...
var g = svg.selectAll(".arc")
.data(pie(json))
.enter().append("g")
.attr("class", "arc");
...
}
index.html:
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);
});
<!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>
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;
}
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
function donut(json) {
...
var g = svg.selectAll(".arc")
.data(pie(json))
.enter().append("g")
.attr("class", "arc");
...
}
data.csv:
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);
});
<!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>
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;
}
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
function donut(json) {
...
var g = svg.selectAll(".arc")
.data(pie(json))
.enter().append("g")
.attr("class", "arc");
...
}
以及:
但它不起作用
我不会使用.csv文件来存储数据,但我想使用数据库。
我该怎么做呢?将d3代码包装成一个函数,每当您以json的形式获取数据时,就会调用该函数 donut.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);
});
<!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>
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;
}
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
function donut(json) {
...
var g = svg.selectAll(".arc")
.data(pie(json))
.enter().append("g")
.attr("class", "arc");
...
}
或者使用从服务器获取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");
...
我的解决方案要求您安装两个附加模块:
npm安装-保存快速车把
和npm安装-保存pg promise
之后,在app.js
中,您可以连接到postgresql服务器,并通过handlebar helpers解析数据,以下是所有相关代码
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);
}
<!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>
这假设您在名为table1的服务器上拥有与csv完全相同的数据结构
然后,您应该在与您的app.js
相同的文件夹中创建一个名为views的文件夹,并创建一个名为home.handlebar
(这是您的index.html
的替代品)
在这个文件中,您需要像这样调用数据{{sqlData}}并对其进行解析
主页。把手
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);
}
<!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>
你可能想问一些更具体的问题——你不知道哪里出了问题。我看到一个奇怪的CSV文件。我设法用CSV(清理后)得到了甜甜圈。@ClemensTolboom我用来做甜甜圈。这只是一个可视化的例子。在我的工作中,我将使用其他图表。如果您对在我的答案中使用该方法感兴趣,我将json解析简化为一行代码。谢谢。
donut()
函数中的json
和d3.json()中的data\u url
是什么?我确信要解决我的问题,有一个非常简单的解决方案,但我不明白..您已将json保存到数据库中,以便您可以使用express代码通过数据库调用获取它,或者当您的数据库支持通过json url获取它时。顺便说一句,我在我的回答中添加了链接。我现在觉得有点愚蠢。在我的数据库中,我有一个表,而不是json。我肯定我可以“下载”json格式的数据,但你的意思是什么?我如何构建url?我很困惑,我想你是说你把csv保存到了数据库里。如果是这样,您可以使用将其转换为数据结构。如果它是一个数据库表,我相信你可以找到一个Express.js来获取d3js可用格式的数据,对吗?谢谢你的回复。数据保存在数据库表中。我当然可以进行查询以获取数据并将其保存在数据结构中(例如json)。我不能做的是组织代码。考虑到在我的项目中,我使用多个使用不同数据的图表。我应该把与可视化相关的代码放在哪里?我如何组织一切?我想看一个具体的例子,说明我想做什么。但是如果我想从脚本文件中拆分home.handlebar
文件,我没有找到任何东西?我创建了一个保存在views文件夹中的donut.js
文件。所以我的home.handlebar
文件包含…
。当我转到时,我获得的上载失败,源代码为“http://localhost:3000/donut.js“
@marielle发布一个新问题,你会从更有nodejs经验的人那里得到更好的帮助