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
这个文件代码是压缩了的,我们先将代码解压,发现我问题出现在这里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | { 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官网,发现有两个预发布版本,我直接看看这里的代码有没有修复,发现是有变化的。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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版本呢?看看修复完成没?
1 | 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。
看下我打的断点输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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重新定义一下,问题解决了。
说到底还是类型的问题,总共也就改了两个地方。
看看最新代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 }) }) |
最后,再将代码压缩下,传到服务器,问题解决了。
这里我把压缩的代码放到这里,供大家直接下载。
This is one of the best explanations I’ve read on this topic.
Online telecharger 1xbet est une plateforme de paris sportifs en ligne. Championnats de football, cotes en direct et resultats sont disponibles. Page d’information sur le service et ses fonctionnalites pour les utilisateurs de la region.
This helped clarify a lot of questions I had.
Envie de parier 1xbet rdc est une plateforme de paris sportifs en ligne pour la Republique democratique du Congo. Football et autres sports, paris en direct et d’avant-match, cotes, resultats et statistiques. Presentation des fonctionnalites du service.
Le site web 1xbet apk rdc propose des informations sur les paris sportifs, les cotes et les evenements en direct. Football, tournois populaires, cotes et statistiques y sont presentes. Ce site est ideal pour se familiariser avec les fonctionnalites de la plateforme.
I always look forward to your posts. Keep it coming!
I love the clarity in your writing.
You write with so much clarity and confidence. Impressive!
You explained it in such a relatable way. Well done!
Thank you for putting this in a way that anyone can understand.