简介:这份地名数据库二期建设总体方案面向GIS、数据库及政府信息化项目人员,系统梳理了省、市、县三级地名数据库共享交换与更新机制的建设路径。资源包共1个doc文件,大小489KB,内容为完整方案文档,目前已有44人学习。方案详述了旧数据库资源(两台服务器、Oracle平台、SuperMap GIS)与一期建设成果,并明确二期建设包括统一标准规范、基础地图更新机制、地名数据库向国家3.0版本迁移、勘界成果建库等环节。其中特别讨论了与国土部门共享基础地图以降低更新成本、10万条沿海地名普查数据逐项拷贝入库的难点,以及采用模型驱动、元数据驱动和SOA架构提升系统扩展性与可维护性。读者可据此掌握此类政务地理信息项目从现状梳理、目标设定到技术方案落地的完整设计思路。
1. 一个被低估的二期工程:地名数据库到底在补什么
做过一期地名数据库的人都知道,最难的往往不是采集那几万条地名,而是二期建设时怎么让这套数据真正活起来。一期上万个图斑、几十个图层、一堆属性字段躺在库里,看起来什么都齐了,但一接业务系统就露馅:坐标对不上、行政区划代码是旧版、自然村和居民点互相压盖。这份《地名数据库二期建设总体方案》解决的就是这类问题——它不是让你重采数据,而是把一期的历史包袱拆开,补齐更新机制、质量规则和数据服务接口,让地名库从「能看」变成「能用」。适合正在做地名库续建、区划调整后数据整改、或准备接共享平台的同行参考。
2. 先盘清三类边界:一期成果、数据现状与服务对象
二期建设动笔写方案之前,我习惯先做三天的「台账盘库」,而不是直接打开数据库看图层。因为二期方案里写的每一个建设内容,都必须回应一个具体问题:一期到底交付了什么、现状数据能不能支撑二期目标、建成后谁在什么场景下用这批数据。这三个边界不搞清楚,方案写出来就是空转。
2.1 一期成果边界:坐标系统、图层结构与字段定义的三层核对
一期项目交付物通常包含三类东西:测绘成果数据(DLG、地名图层)、属性数据库(Access、Oracle或PostgreSQL)、以及元数据文档。但实际收到的成果里,最容易出问题的是坐标系统和字段别名不一致。某次我接手一个二期的活儿,发现一期的数据存在两套坐标:城区范围用的是2000国家大地坐标系,乡镇图层却还是西安80的老成果,两套数据叠在一起直接差出几十米。
核对坐标系统时,我一般会写一条简单的查询语句,把每个图层的空间参考ID拉出来对比:
SELECT f_table_name, srid, split_part(srtext, '"', 4) AS projection_name FROM spatial_ref_sys WHERE srid IN (SELECT DISTINCT st_srid(geom) FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname LIKE '%geo%' AND c.relkind = 'r');这条SQL在PostgreSQL里把涉及地理实体的表空间参考ID一次性列出来,我习惯用2系和3系开头的SRID做快速判定:CGCS2000的SRID通常是4490或4547到4552之间的高斯投影带,西安80则是2382到2395这一段。如果同一份数据里同时出现两段SRID,就不要指望软件自动转换——二期方案里必须单独列一节坐标统一。字段别名的问题更隐蔽,常见的是「地名类别」在一期里叫DLMC,在另一个图层里叫MC,需要建一张字段映射表,而不是靠嘴上交代。
2.2 现状调研:把「谁在用、怎么用、缺什么」问成一张表
边界盘查的第二件事是找人聊。二期方案里我会放一张调研表,分成三列:使用方、使用场景、数据诉求。使用方通常包括内部业务科室、测绘成果管理部门、以及需要接地名数据的其他业务系统;使用场景则要区分是查询检索、地图展示、还是统计分析。
调研对象不同,反馈的诉求完全不一样。业务科室关心的是地名类别字段够不够细——比如「村委会」和「村民委员会」在一期数据里混着写,统计分析时根本算不准;测绘成果管理部门关心的是增量更新之后版本怎么管理,生怕更新一次把上一版覆盖掉;接数据的系统最关心接口返回的字段是不是稳定——上个月还叫XZQH,这个月改叫XZDM,对接的人就得改代码。我一般会把每一条诉求记成「现状描述 + 期望改变」的格式,写进方案的调研纪要附件里。
2.3 服务对象决定建设序列:三类需求对应不同的优先级
调研完会发现,服务对象其实可以归成三类,每类对二期建设的优先级要求不一样。政务共享类要的是标准化接口和稳定的字段结构;公众服务类要的是数据现势性,地名更新后要在规定时间内能查到;内部管理类要的是数据质量和审核流程。三类需求同时提出来,方案里就要给出建设序列,先做标准、再做接口、最后做更新机制,而不是眉毛胡子一把抓。
我见过一个翻车案例:某项目二期先上了公众服务的地名查询接口,但数据质量规则还没建,结果地址匹配的时候,同一条路在系统里出现「中山路」「中山西路」「中山路西段」三条记录,用户一搜地址全乱套。后面只好回炉补质量规则。所以我的习惯是:服务对象决定建设序列,建设序列反过来约束方案章节的排布——标准先行、更新跟上、接口最后。
3. 把地名拆成能落地的标准:分类代码、属性结构与坐标框架
地名数据库二期最容易写虚的就是「标准化」这一章——如果通篇都是「完善地名分类体系」这种话,等于什么都没写。要把标准落地,至少要有三样东西:一套能直接入库的分类代码、一张字段级属性结构表、以及一个坐标框架和地理实体编码的绑定规则。这三样定下来,数据层面的地基才算打完。
3.1 分类代码:用「门类—大类—小类」三级编码兜住地名多样性
地名分类的坑在于:行政区地名、自然地名、人文地名混在一起,直接用字符串存类别名,后续统计全靠人工认字。我的做法是采用三层编码,第一层是门类(用一位数字):1是自然地名,2是人文地名,3是行政区地名;第二层是大类(两位数字),细分到水系、地形、交通、水利设施等;第三层是小类(两位数字),具体到河流、湖泊、公路、铁路、立交桥。整个编码是一个五位数字串,入库时强制校验。
{ "code": "10201", "name": "常年河", "level": 3, "parent": "102", "remarks": "门类1-自然地名,大类02-水系,小类01-河流" }这段JSON是地名分类目录里常见的一种描述方式,我一般在建标准时把全部分类条目抽到这个结构里,方便后续做代码表管理。code是最终入库的编码,level表示层级,parent指向上一层编码。这样做的好处是新增地名词条时不用动整个体系,只需要在对应大类下追加小类编码,且编码中间不留空洞,保证统计时能按前缀汇总。比如所有102开头的地名都是水系相关的,一条SQL就能group by出全区域河流数量。
3.2 属性结构:核心字段一张表说清,别名问题一次性解决
属性结构表是二期方案里最容易被忽略、但后期返工最多的部分。我见过一期数据里有四十多个字段,一半是空值,还有五六个字段语义重叠。二期定属性结构时,我会遵循「核心字段不过二十个」的原则,把必填项压到最少,能通过编码表推导出来的字段就不单独存储。
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| GBCODE | VARCHAR(10) | 是 | 地名分类代码,按三级编码填写 |
| NAME | VARCHAR(100) | 是 | 标准地名名称 |
| ALIAS | VARCHAR(200) | 否 | 别名,多个用半角分号分隔 |
| XZQH | VARCHAR(12) | 是 | 行政区划代码,按现行国标 |
| LONGITUDE / LATITUDE | NUMERIC(10,6) | 是 | 代表点坐标 |
| SOURCE | VARCHAR(50) | 是 | 数据来源,如外业采集、影像判读 |
| STATUS | SMALLINT | 是 | 0-草稿 1-审核通过 2-已废止 |
这张表里最有讲究的是STATUS字段,它承载了二期的生命周期管理。一期数据里没有这个字段,导致废止的地名只能物理删除,一旦上级核查发现这条地名应该保留历史记录,就得从备份里捞。二期建库时把STATUS设为必填,废弃地名一律置为2而不是删除,既保住了历史可追溯,又不会影响现势查询。XZQH字段单独存放行政区划代码,是为了避免每次查询都去做空间叠加判断——毕竟地名数据接共享平台时,按行政区过滤是最常见的查询方式。
3.3 坐标框架:一张图说清地理实体编码怎么挂到地名上
坐标框架的落地是指地名数据的每个图斑都要能对应到一个地理实体编码,这样后续更新时才能精准定位到「哪条河、哪个村」。地理实体编码我习惯用「行政区划代码 + 顺序号」的拼接方式,比如某县代码加四位流水号,保证县域内不重复。代表点坐标建议统一存储经纬度十进制度数,投影坐标放在单独的投影字段里,避免两套坐标混存。
实际建库时常见一个玄学问题:坐标数值看起来是对的,但地图上一显示就跑偏。后来排查发现是经纬度字段精度设置成了NUMERIC(8,6),小数位截断导致百米级偏移。所以我在方案里会特别注明精度约束必须到10位有效数字,并且加上一条检查规则:经度范围0到180,纬度范围0到90,不在范围内的一律拦截入库。
4. 增量更新不只是人工跑:流程、接口与冲突处理
二期建设里更新机制是重头戏。一期基本都是整库更新,每次新数据下来就整体替换一遍,时间一长版本全乱。二期方案里要把更新机制做成常态化流程:平时只提交变更记录,定期合并到主库,这样既减少了全量替换的数据量,又能保留每次变更的痕迹。但增量更新一旦涉及多人在线作业,冲突问题就会冒出来,方案里必须给出明确的处理策略。
4.1 两条更新线:图上作业与表格录入最终要汇到同一张审核表
地名更新的入口通常有两个:一是测绘人员在地图上勾绘图斑并修改属性,二是业务人员直接在表格里录入名称变更。两条线如果不做合并,就会出现同一条地名被两个人改了不同字段,最后数据对不上的情况。我会在方案里设计一张统一的变更申请表,无论是图上作业还是表格录入,最终都要落进同一张表里,带着操作人、操作时间、变更类型和变更前后值。
CREATE TABLE geo_change_log ( change_id SERIAL PRIMARY KEY, feature_gid BIGINT NOT NULL, change_type SMALLINT NOT NULL, -- 1新增 2修改 3废止 field_name VARCHAR(50), old_value TEXT, new_value TEXT, operator VARCHAR(50), change_time TIMESTAMP DEFAULT now(), review_status SMALLINT DEFAULT 0 -- 0待审核 1通过 2驳回 );这张变更日志表是整个更新流程的中枢。feature_gid关联到地名图斑的唯一标识,change_type记录操作类型,field_name加上old_value/new_value能精确到字段级变更,这样审核人不用打开GIS软件就能在页面上完成复核。最关键的字段是review_status,默认0表示待审核,审核通过后才允许合并进主库。我把这条设计放进方案时,有同行问为什么不直接改主库再记日志,原因是直接改主库遇到审核驳回时很难恢复原值——先记日志、审核通过再回放,相当于给每次更新留了后悔药。
4.2 增量包结构:边界范围、变更清单与回滚脚本三件套
增量更新不能只传一个SHP文件,那样接收方根本不知道改了哪些地方、哪些记录过期了。我会在方案里规定增量包必须包含三样东西:变更范围(一个面图层,标注本次更新涉及的行政区域)、变更清单(上面那张geo_change_log导出的记录)、以及回滚脚本。回滚脚本很多人不做,但一旦合并后发现问题,没有回滚就只能靠备份恢复,代价极大。
在实际指导某次更新作业时,我一般要求合并更新前先执行一个校验脚本,比对增量数据与主库数据的版本号。主库要有一个全局版本号字段,每次合并成功就加一,增量包上标注目标版本号——只有主库当前版本与增量包期望版本一致才允许合并。这个版本号机制看起来多余,但能挡住绝大多数并发更新导致的数据串包问题。
4.3 冲突处理:先到先得是陷阱,按字段级别合并才靠谱
多人同时更新时冲突不可避免,但冲突处理策略很多项目根本没写进方案。最容易翻车的做法是「后提交覆盖先提交」——某区同时改了三条地名的名称字段和类别字段,A提交了名称修改,B提交了类别修改,后提交的B把A改的名称也覆盖回旧值了。我会在方案里明确冲突处理按字段级合并:只有同时修改同一字段且前后值不一致才算真正冲突。
真正冲突的仲裁原则我建议用「角色优先 + 时间戳兜底」:管理员审核通过的记录优先于普通作业员的记录,如果同一字段两条记录都审核过,则取change_time最新的。这套规则写进方案后要同步写进审核页面的交互逻辑里,让审核人看到冲突的双方值和提交时间,而不是让系统静默选择。这里还有一个容易被忽略的细节:冲突记录不能被吞掉,要进一张单独的冲突表,保留双方原始值,方便后续追溯。
5. 质量核查与常见问题排查:拓扑、逻辑与我的踩坑记录
数据质量核查是二期建设里最像「黑匣子」的环节——规则跑完报了几千条错误,但没人能说清哪些是真错、哪些是正常情况。我做过几个地名库的质量核查模块之后,最大的感受是:规则要分级、错误要分类、结果要能追溯。这章把我的核查思路和踩过的坑一起写出来。
5.1 质量规则分三级:几何、属性、逻辑,过滤掉假错误
质量规则不要一股脑全跑,我会把它拆成几何规则、属性规则、逻辑规则三级。几何规则查拓扑关系,比如面图斑不能重叠、不能有悬挂线;属性规则查空值和非法值,比如必填字段不能为空、行政区划代码必须符合国标;逻辑规则查字段间的矛盾,比如名称字段写「XX村」但类别编码是「河流」这种明显不对的组合。三级规则分开跑,就是为了能单独定位问题在哪一层。
跑规则时有个常见坑:几何重叠检查会把相邻图斑的公共边报成重叠错误,因为相邻多边形本来就有共享边界。我一般会把容差设成0.5米,小于这个距离的公共边不算重叠,但把这个参数写进方案时一定要注明——容差设太大,真重叠也查不出来。
5.2 核查脚本示例:一条SQL抓住重复地名和越界坐标
质量核查不是非得上大平台,日常用PostGIS写几条检查SQL就够了。我常用的一个检查是查重复地名:同一行政区划代码下,名称相同且类别相同的记录视为疑似重复。
SELECT xzqh, name, gbcode, count(*) AS dup_cnt, array_agg(gid) AS gid_list FROM geo_place WHERE status = 1 GROUP BY xzqh, name, gbcode HAVING count(*) > 1;这条SQL在审核阶段跑一遍,能快速圈出同一县区内重名且同类的记录。gid_list列会把重复记录的ID都列出来,审核人按这个列表决定保留哪条、废止哪条。另一个常用检查是坐标越界:
SELECT gid, name, lon, lat FROM geo_place WHERE lon NOT BETWEEN 73 AND 135 OR lat NOT BETWEEN 3 AND 53;这里把经纬度范围设为中国大陆的粗略外框,超出这个范围的基本可以判定为坐标录入错误,比如经纬度写反或者小数点位错。这两条SQL我一般直接写进方案的质量核查章节,供实施单位复制改成适配自己表结构的版本。
5.3 常见问题排查:现象、原因、解决
以下是我在这类项目里反复踩过的四个问题,每条都按「现象→原因→解决」写清楚。
问题一:更新合并后部分地名凭空消失。现象:增量包合并完,主库里的记录反而少了十几条。原因:增量包里的变更清单把部分记录标记成了废止,而废止操作没有经过审核流程就合并了。解决:在合并程序里加一道强制校验,凡change_type为3的记录必须携带review_status=1的审核依据,否则拒绝合并。
问题二:坐标检查没报错,但地图显示位置偏离一条街。现象:经纬度在合理范围内,但图斑叠加到影像底图上偏移几十米。原因:字段精度被数据库默认值截断了——某次建表时经纬度字段被建成NUMERIC(8,5),小数位只保留五位,导致秒级精度丢失。解决:改字段精度为NUMERIC(10,7),并加一条持久化检查规则,任何经纬度字段的精度低于10位有效数字都不允许建表。
问题三:增量更新后统计报表出现两条同码不同名的记录。现象:同一GBCODE下出现两个名称,报表合计数量翻倍。原因:不同审核人员对同一地名的修改都通过了审核,两条记录共享一个分类代码但名称不同,系统没有在合并时查重。解决:更新合并动作里内置查重步骤,同一行政区划下名称和类别都相同的记录只能保留一条,其余转人工裁决。
问题四:质量核查报告里的错误数量每次跑都不一样。现象:同一份数据连续跑两次检查,错误数量对不上。原因:检查规则里用了随机抽样函数,抽查样本每次都不同。解决:抽查必须固定随机种子,或直接把抽查改为全量检查——地名词条量级本来就不大,全量检查性能完全撑得住。
6. 从方案到验收:验证清单与二次开发的关键细节
方案写到最后一章,要回答的问题只有两个:怎么证明这套建设达成了目标?二期数据能怎么往下扩展?我习惯把验收验证清单和二次开发要点绑在一起写,因为验收通过不是终点,二期数据要能接上新场景才算真正落地。验证清单我按四条线组织:数据完整性、坐标正确性、更新闭环、接口稳定性。
数据完整性看的是图斑数量、属性字段完整率、分类代码覆盖率;坐标正确性看抽查点叠加影像的偏移量;更新闭环看一次完整的变更从提交到审核到合并再到对外发布能不能走通;接口稳定性看连续调用响应时间和返回字段的一致性。这四条线每条都要有具体的通过阈值。阈值定多少我一般按项目实际定,比如字段完整率不低于99.5%,接口响应不超过1秒,抽查点偏移不超过2米。
二次开发的关键细节我会额外提到变更日志的留存策略。geo_change_log表只保留最近一年的记录,超过一年的归档到历史表,避免主表膨胀拖慢查询。归档时要把change_id和feature_gid的关联关系一并保留,否则回溯历史版本时找不到对应图斑。
另一个容易被忽视的细节是版本快照。每次合并更新后,我会手动导出一次主库的只读快照存到离线存储里,存够最近三个版本即可。这个习惯看起来笨,但曾经救过我一次——某次增量包里的坐标字段因为程序bug写错了基准面,合并后大面积偏移,靠rollback脚本修不干净,最后是直接回滚到前一天快照才恢复的。从那以后我每次做版本合并,都会在脚本里强制加一步快照导出,哪怕目标存储只剩几百MB空间也要先腾出来。希望这点经验能帮你在二期验收和后续维护里少走一段弯路。
本文还有配套的精品资源,点击获取