我对crossfilter和dc很陌生,目前正在尝试与它们构建交互式仪表板。我的数据很容易上升到200MB左右,当我在客户端进行交叉过滤时,我的浏览器就会崩溃,所以经过一些在线搜索后,我决定在服务器上运行crossfilter,在客户端运行dc以便绘图,而我我在这里工作dc.js-server-side-crossfilter但是,dc图表并没有相互影响。
从我理解的基本组件来看,服务器端app.js处理从客户端app.js发送的Ajax调用,并执行所需的过滤,然后将JSON格式的维度和组发送回客户端 - 然后我们将创建假维度和组并将它们输入到dc图表中,然后每个用户点击/拖动图表然后再次创建另一个Ajax调用,整个过程再次重复。
在这里,我将有些伪代码发布到重要部分,因为原始内容很麻烦,
服务器端app.js
var app = express();
// define variables that will get passed
var dimensions = {};
var groups = {};
// handle the ajax call coming from client-side
app.get("/refresh", function(req, res, next){
var results = {};
filter = req.query["filter"] ? JSON.parse(req.query["filter"]) : {}
for(group_i in groups){
var group = groups[group_i];
if(filter[group_i]){
dimensions[group_i].filter(filter[group_i]);
}
results[group_i]= {values:group.all(),
top: group.top(1)[0].value,
};
}
// send result back in JSON
res.writeHead(200, { 'content-type': 'application/json' });
res.end((JSON.stringify(results)));
});
load data into memory {
// do crossfiltering
var cf = crossfilter(data);
// dimensions
var dateDim = cf.dimension(function(d) {return d['timestamp'];});
var typeDim = cf.dimension(function(d) {return d['destination_type'];});
// groups
var numByDate = dateDim.group();
var numByType = typeDim.group();
// put these dimensions and groups into corresponding variables
dimensions.dateDim = dateDim;
dimensions.typeDim = typeDim;
groups.numByDate = numByDate;
groups.numByType = numByType;
}
客户端app.js
var timeChart = dc.barChart("#pvs-time-chart");
var filteredData = {};
var queryFilter = {};
var refresh = function(queryFilter){
// make ajax call
d3.json("/refresh?filter="+JSON.stringify(queryFilter), function(d){
filteredData = d;
dc.redrawAll();
});
}
var fakeDateDim = {
filter: function(f){
if(f){
queryFilter["dateDim"]=f;
refresh(queryFilter);
}
},
filterAll: function(){
}
};
var fakeNumByDate = {
all: function(){
try{
var dateFormat = d3.time.format("%Y-%m-%d");
filteredData["numByDate"].values.forEach(function (d) {
d['key'] = dateFormat.parse(d['key']);
});
}
catch(err) {
// console.log(err);
}
return filteredData["numByDate"].values;
},
order: function(){
},
top: function(){
}
};
// Make charts
timeChart
.width(1200)
.height(250)
.margins({top: 10, right: 50, bottom: 30, left: 50})
.dimension(fakeDateDim)
.group(fakeNumByDate)
.transitionDuration(500)
.x(d3.time.scale().domain([minDate, maxDate]))
.elasticY(true)
.renderHorizontalGridLines(true)
.yAxis().ticks(4);
timeChart
.filterHandler(function(dimension, filters){
if (filters) {
dimension.filter(filters);
}
else {
dimension.filter(null);
};
return filters;
});
// Similarly for typeChart
var typeChart = dc.rowChart("#dest-type-row-chart");
...
function init(){
d3.json("/refresh?filter={}", function(err, d){
filteredData = d;
dc.renderAll();
});
}
init();
我真的不知道为什么这两个图表没有互相交流,有什么建议吗? (我很抱歉,如果他们是明显的事情)
修改:
数据从mongodb数据库加载。
这两个图都正确显示,所以我认为数据本身及其分组方式不存在问题。
没有错误被抛出。服务器端调试显示(每个用户单击/拖动):
GET /refresh?filter={%22dateDim%22:[[%222017-08-13T21:10:30.937Z%22,%222017-
09-08T16:02:52.755Z%22]],%22typeDim%22:
[%22Player%22,%22Schedule%22,%22Other%22,%22Game%20Stats%22]} 200 8.333 ms -
-
客户端没有显示错误。
问题是,当您在选定的维度和组上创建两个直流图表时,他们应该根据两个图表中任何一个图表上的用户操作进行交互/更改,但是现在设置的方式是用户操作(任何一个图表上的点击/拖动都不会触发对其他图表的更改,条形图仍然可以被点击但没有任何变化。
相关链接我也检查过:
BIG DATA VISUALIZATIONS USING CROSSFILTER AND DC.JS
Using dc.js on the clientside with crossfilter on the server