Superset Filter box报错Cannot read property ‘map’ of undefined的解决方案

最近在用superset做数据分析时,用到了 Filter box筛选框,筛选其他的类型没什么问题,只要是日期有关的筛选,所有的筛选框都会消失,我安装superset是用pip安装的,版本号是0.28.1。如图报错:


首先想到的解决方案就是去github查找issues,果真很多同学都遇到了这个问题。
然后也找了两个解决办法:
https://github.com/apache/incubator-superset/commit/912c6f623159be69007cc9ee38b10e8adc7778ce
https://github.com/lyft/incubator-superset/commit/57410671fb90aa86433274eb6dd644b134b92dbe
但是解决的都是源码的问题,pip安装的都是编译好的,而且代码都不一样。
最终我通过看源代码,一个个打断点将这个问题解决了。
首先看文件
/usr/local/lib/python3.7/site-packages/superset/static/assets/dist/filter_box.885b5b9fd31f4d3caa48.chunk.js
这个文件代码是压缩了的,我们先将代码解压,发现我问题出现在这里:
{
key: "renderFilters",
value: function() {
return function() {
var e = this
, t = this.props
, n = t.filtersFields
, r = t.filtersChoices
, a = this.state.selectedValues;
return Object.keys(a).filter(function(e) {
return !(a.hasOwnProperty(e) && e in r)
}).forEach(function(e) {
var t = r[e]
, n = new Set(t.map(function(e) {
return e.id
}));
a[e].filter(function(e) {
return !n.has(e)
}).forEach(function(n) {
t.unshift({
filter: e,
id: n,
text: n,
metric: 0
})
})
}),
n.map(function(t) {
var n = t.key
, u = t.label
, s = r[n]
, c = Math.max.apply(Math, function(e) {
if (Array.isArray(e)) {
for (var t = 0, n = Array(e.length); t < e.length; t++)
n[t] = e[t];
return n
}
return Array.from(e)
}(s.map(function(e) {
return e.metric
})));
return o.default.createElement("div", {
key: n,
className: "m-b-5"
}, u, o.default.createElement(p.default, {
placeholder: (0,
v.t)("Select [%s]", u),
key: n,
multi: !0,
value: a[n],
options: s.map(function(e) {
var t = Math.round(e.metric / c * 100)
, n = {
backgroundImage: "linear-gradient(to right, lightgrey, lightgrey " + t + "%, rgba(0,0,0,0) " + t + "%",
padding: "2px 5px"
};
return {
value: e.id,
label: e.id,
style: n
}
}),
onChange: function() {
for (var t = arguments.length, r = Array(t), o = 0; o < t; o++)
r[o] = arguments[o];
e.changeFilter.apply(e, [n].concat(r))
},
selectComponent: l.Creatable,
selectWrap: i.default,
optionRenderer: (0,
h.default)(function(e) {
return e.label
})
}))
})
}
}()
},
通过看代码逻辑var t = r[e]是一个undifined,因为上面的过滤return !(a.hasOwnProperty(e) && e in r),可以判断出e不是r里面,所有r[e]没有,而下面的t.map必须要求t是一个数组,所以这里代码报错了。
首先我去看了pip官网,发现有两个预发布版本,我直接看看这里的代码有没有修复,发现是有变化的。
key: "renderFilters",
value: function() {
return function() {
var e = this,
t = this.props,
n = t.filtersFields,
r = t.filtersChoices,
a = this.state.selectedValues;
return Object.keys(a).filter(function(e) {
return a.hasOwnProperty(e) && e in r
}).forEach(function(e) {
var t = r[e] || [],
n = new Set(t.map(function(e) {
return e.id
}));
(Array.isArray(a[e]) ? a[e] : [a[e]]).filter(function(e) {
return !n.has(e)
}).forEach(function(n) {
t.unshift({
filter: e,
id: n,
text: n,
metric: 0
})
})
这里的筛选条件变了,return a.hasOwnProperty(e) && e in r,以前是非,现在与。
直接替换这里的代码,报错,不行。
那么我直接安装0.29版本呢?看看修复完成没?
pip install superset==0.29.0rc7
安装完成,运行superset runserver -d
报错,说是flask1.0版本废弃了命令,试用flask run 什么的。
居然运行不起来,然后我查了一下superset runserver -help
试着不用-d参数superset runserver居然成功了,真是奇怪了。
然后运行 127.0.0.1:8088,发现搜索框是好的。看来新版本是解决了这个问题。
当然如果线上运行的是0.28.1版本的,不想升级怎么办呢。
继续调试bug。
看下我打的断点输出:
var e = this,
t = this.props,
n = t.filtersFields,
r = t.filtersChoices,
a = this.state.selectedValues;
console.log('第一步:',e)
console.log('第二步:',t)
console.log('第三步:',n)
console.log('第四步:',r)
console.log('第五步:',a)
return Object.keys(a).filter(function(e) {
console.log('第1步:',e)
console.log('第2步:',a.hasOwnProperty(e))
console.log('第3步:',e in r)
return !(a.hasOwnProperty(e) && e in r)
}).forEach(function(e) {
var t = r[e];
console.log('第七步:',t)
console.log('第八步:',e)
那么我将t重新定义一下r[e] || [],然后发现a[e].filter这里报错,filter函数也需要是一个数组,可是a[e]是一个值,我们把它变成一个数组,Array.isArray(a[e]) ? a[e] : [a[e]]。这里改好以后,这里n.map也报错,原来这里的n已经被上面的forEach的回调函数改了,这个n应该是上面n = t.filtersFields的值,这里我们改一下将n重新定义一下,问题解决了。
说到底还是类型的问题,总共也就改了两个地方。
看看最新代码:
var t = r[e] || [],
n = new Set(t.map(function(e) {
return e.id
}));
(Array.isArray(a[e]) ? a[e] : [a[e]]).filter(function(e) {
return !n.has(e)
}).forEach(function(n) {
t.unshift({
filter: e,
id: n,
text: n,
metric: 0
})
})
最后,再将代码压缩下,传到服务器,问题解决了。
这里我把压缩的代码放到这里,供大家直接下载。
PHP面对对象设计模式之适配器模式 让PHPStorm 支持 Vue的方法
文章不错支持一下吧
文章不错支持一下,非常喜欢
文章不错支持一下吧
文章不错支持一下吧
文章不错支持一下吧
非常感谢!替换完之后重新登录清除下浏览器缓存就可以用了!
能帮助到您真是开心!