filter 里数字和字符串比较,条件永远是 false
明明有 40 个区县人口超过一万,图层上一个都没画出来,也没有报错。
现象
图层 filter 写成:
filter: ['>=', ['get', 'pop'], 10000]
数据里 pop 是字符串(GeoJSON 属性来自 CSV,全部带引号),
结果 queryRenderedFeatures 返回 0 条,
控制台没有类型错误,只有图层 visibility 正常、颜色正常,就是不显示。
原因
Mapbox 样式的表达式系统是强类型的,不做隐式转换。
['get','pop'] 返回字符串 "12000",
与数字 10000 比较时,类型不匹配,
比较结果为 false,且不会抛错。
类似地,filter: ['==', ['get','level'], 2]
在 level 为 "2" 时同样恒为 false。
这类问题最难查,因为没有错误信息,只有「没画出来」。
| 属性值 | 比较 | 结果 |
|---|---|---|
"12000" | >= 10000 | false |
12000 | >= 10000 | true |
"2" | == 2 | false |
"2" | == "2" | true |
排查过程
- 取一条要素,打印
typeof f.properties.pop,确认是字符串还是数字。 - 把 filter 去掉,看要素是否正常显示,确认是过滤而非样式问题。
- 用
['to-number', ['get','pop']]包一层,若恢复正常即可定位。 - 检查数据源:CSV 转 GeoJSON 时属性常全为字符串,需要显式转换。
const f = map.querySourceFeatures('districts')[0];
console.log(f.properties.pop, typeof f.properties.pop);
// "12000" string
// 去掉 filter 验证
map.setFilter('districts', null); // 要素出现 -> 过滤条件有问题
解决方案
比较前显式转换,或在数据入库时就转成数字。
map.addLayer({
id: 'districts',
type: 'fill',
source: 'districts',
filter: ['>=', ['to-number', ['get', 'pop']], 10000],
paint: { 'fill-color': '#1a6fd4', 'fill-opacity': 0.6 }
});
// 字符串比较则统一加引号
map.setFilter('districts', ['==', ['get', 'level'], '2']);
// 需要排除无法解析的情况
map.setFilter('districts', [
'all',
['has', 'pop'],
['>=', ['to-number', ['get', 'pop'], 0], 10000]
]);
数据侧也应该修:GDAL 导出时用 -fieldTypeString 之外的默认类型,
或写一个小脚本把所有数值型字段转成 number。
fc.features.forEach(f => {
['pop', 'area'].forEach(k => {
if (k in f.properties && typeof f.properties[k] === 'string') {
const n = Number(f.properties[k]);
if (!Number.isNaN(n)) f.properties[k] = n;
}
});
});
验证
queryRenderedFeatures 返回的记录数应等于数据中满足条件的数量(本例约 40 条),
且每条 properties.pop 为 number 类型。
const r = map.queryRenderedFeatures({ layers: ['districts'] });
console.assert(r.length === 40, '过滤结果数量不符:' + r.length);
console.assert(typeof r[0].properties.pop === 'number', '属性仍为字符串');
适用版本
| 库 | 版本 | 说明 |
|---|---|---|
| Mapbox GL JS | 2.15 / 3.x | 表达式强类型,无隐式转换 |
| MapLibre GL JS | 3.x / 4.x | 行为一致 |
| Mapbox 样式规范 | v8 | to-number 可带兜底默认值 |
经纬志(2026)。《filter 里数字和字符串比较,条件永远是 false》。https://www.jingweizhi.com/cookbook/filter-number-vs-string.html(访问日期 2026-11-03)。