地理位置维度
如何关联我们系统的地理位置维度(现实地理位置)
或者自己新建一个自定义地理位置维度。
一、如果你们系统中的地理位置架构用的是现实地理位置架构。
那么在我们系统中不用建模,直接系统设置->导入内置概念包->导入 geo
下面我来介绍 etl 如何关联上我们系统的地理位置。
关联我们地理位置的必要性在于 我们内置了大量的地理位置的同义词,并且只有关联我们的才能呼出地图
我们系统地理位置的名称基本和行政区划保持一致,id 略有不同
现实地理位置(行政区划)介绍
url:https://www.mca.gov.cn/mzsj/xzqh/2022/202201xzqh.html
我们系统地理位置 id 的 hierarchy(层级)结构:
通过ID的长短来分层(156是中国,还有全球其他国家)
规则 示例ID 名称
国家:三位156 156 中国
区域:四位156a 1564 华东地区
省市:六位156abc 156434 安徽省
城市:八位156abcde 15643408 安庆市
区县:十位156abcdefg 1564340811 宜秀区
在这种层级架构下,只要知道了区县,其他省市信息等也都包含在了区县里了。
1、你们系统中存储的地理位置 id 是行政区划代码
我们系统中区县代码后六位和中华人民共和国县以上行政区划代码保持一致。
这就意味这如果如果你们系统中存储的地理位置 id 是行政区划代码,
就可以通过把我们的 geo 表导入数据库,然后关联得到我们系统 geo 的 ID。
2、你们系统中存储的地理位置 name 是标准的行政区名称
通过名称关联,拿 ID
show tables;
-- geo是我们系统的表
-- cgeo是你们系统的表
-- 查看表结构
desc geo;
desc cgeo;
-- 判断id或者name哪种关联方式的准确率比较高
-- 想要完全一致,每一行都catch到是比较困难的,行政区划每年都会有id和名称的更新
-- 所以最后还是需要辅以一定的人工校准
select *
from cgeo t1
left join geo t2 on t1.id = RIGHT(t2.ID, 6)
where t2.id is null;
select *
from cgeo t1
left join geo t2 on t1.name = t2.名称
where t2.名称 is null;
-- 上面两个sql得出结论 通过名称关联比较好
-- 然后我们拿geo的id
-- 注意:这里仅展示维度cgeo关联geo,实际场景下应该是事实表区关联geo获取geo.id
select t2.id
from cgeo t1
left join geo t2 on t1.name = t2.名称
where t2.名称 is not null;
-- 未关联上的cgeo怎么处理?
-- 部分 查询id 或 名称
-- 例子:cgeo 中 340212 繁昌区 没关联上
select *
from geo
where id like '%340212%'
or 名称 like '%繁昌%'
;
二、如果你们系统中的地理位置架构用的是自定义层级架构。
1、geo 实体表不能用们系统内置的了,需要重新建 schema
需要对我们系统有一定了解的人员进入专家模式实施,
geo 的 ID 标准化使用上面的根据长度设置层级架构,
这样的好处就是可以从最顶层下钻到最下层。
级别 长度 ID 名称
国 4 9527 中国
大区 2 952701 安徽一区
中区 2 95270101 安庆一区
小区 2 9527010101 宜秀一区
2、自定义的地理位置支持地图比较复杂,如有需求请联系管理人员。
三、 关于如何配置自定义层级结构的文档
四、 算法自动化转换数据库表生成hierarchy架构
提供测试的csv数据
"id","name","parentId"
"100", "a", null
"10", "b", "100"
"102", "c", "100"
"103", "d", "10"
"104", "e", "10"
"105", "f", "102"
结果JSON预览
[
{ id: '100', parentId: null, newId: '001', name: 'a' },
{ id: '10', parentId: '100', newId: '001001', name: 'b' },
{ id: '102', parentId: '100', newId: '001002', name: 'c' },
{ id: '103', parentId: '10', newId: '001001001', name: 'd' },
{ id: '104', parentId: '10', newId: '001001002', name: 'e' },
{ id: '105', parentId: '102', newId: '001002001', name: 'f' }
]
代码:输入csv输出excel。 请根据实际情况调整代码输入输出。
const fs = require("fs");
const Papa = require("papaparse");
const XLSX = require("xlsx");
// 读取 CSV 数据
const csvData = fs.readFileSync("test.csv", "utf-8");
const parsedData = Papa.parse(csvData, { header: true }).data;
function buildHierarchy(orgs) {
const map = new Map();
let rootNodes = [];
let maxLevel = 0;
// 创建所有节点并初始化 children 数组
orgs.forEach((org) => {
map.set(org.id, { ...org, children: [] });
});
// 构建层级结构
orgs.forEach((org) => {
if (org.parentId && map.has(org.parentId)) {
const parent = map.get(org.parentId);
parent.children.push(map.get(org.id));
} else {
rootNodes.push(map.get(org.id));
}
});
// 递归生成新的 ID、层级信息和是否为末端节点
function generateMetadata(nodes, prefix = "", level = 1) {
maxLevel = Math.max(maxLevel, level);
nodes.forEach((node, index) => {
const newId = prefix + String(index + 1).padStart(3, "0");
node.newId = newId;
node.level = level;
node.isLeaf = node.children.length === 0;
if (!node.isLeaf) {
generateMetadata(node.children, newId, level + 1);
}
});
}
generateMetadata(rootNodes);
return {
hierarchyData: Array.from(map.values()).map(
({ id, parentId, newId, name, level, isLeaf }) => ({
id,
parentId,
newId,
name,
level,
isLeaf,
})
),
maxLevel,
};
}
const { hierarchyData, maxLevel } = buildHierarchy(parsedData);
console.log(hierarchyData);
console.log("最大层级数:", maxLevel);
// 生成层级数据结构
const levelStructure = Array.from({ length: maxLevel }, (_, i) => ({
name: `第${i + 1}层`,
syno: `["第${i + 1}层"]`,
code_length: 3,
}));
console.log("层级结构:", levelStructure);
// 导出 JSON 到 Excel
function exportToExcel(data, filename = "output.xlsx") {
const worksheet = XLSX.utils.json_to_sheet(data);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Hierarchy Data");
XLSX.writeFile(workbook, filename);
console.log(`Excel 文件已生成: ${filename}`);
}
exportToExcel(hierarchyData);