docs: 更新版本号0.1.3 并同步语义匹配模块说明及参数
一个基于 MoonBit 编写的地理信息数据库,专门用于存储、解析、检索中国地址信息。
# 一键演示 61 POI(13 城市簇)+ 全部核心功能 moon run cmd demo # 语义地址匹配(20k 真实地址评测语料) moon run cmd addr-match "汉中路180号星汉大厦26楼江苏东方燃油有限公司" "汉中路180号星汉大厦26层A江苏东方燃油有限公司" moon run cmd addr-eval testdata/data.txt 0 # 全量 20k × 5 candidates 评测 moon run cmd corpus-db 500 # 从真实语料构建空间 DB # 性能基准(默认 1000,可指定 10000 等更大规模) moon run cmd benchmark 10000 # 完整测试套件 moon test # 339/339 passed # 高级空间分析示例 moon run cmd kmeans 3 # K-Means 聚类(3 大宏观区域) moon run cmd dbscan 50.0 3 # DBSCAN 密度聚类(自动识别 13 城市簇) moon run cmd tsp-2opt bj-gugong # TSP + 2-opt 路线优化 moon run cmd idw 35.0 115.0 2.0 # IDW 空间插值 moon run cmd kriging 35.0 115.0 12 # Kriging 克里金插值 moon run cmd concave-hull 1.5 # 凹包 (Alpha-Shape) moon run cmd moran-i-knn # Moran's I (KNN 权重) moon run cmd sde # 标准差椭圆
demo 命令在 61 POI 样本库上依次演示:按 ID/名称检索 → 附近查询 → K-Means 宏观分区 → DBSCAN 城市簇识别(13 簇 + 3 远郊噪声点) → 标准差椭圆 → TSP NN+2-opt(节省约 265 km)→ IDW/Kriging 插值 → 凹包 → 中文地址解析。
demo
.tmp
find_bbox(min_lat, max_lat, min_lng, max_lng)
本版本针对查询性能进行了多项优化:
find_in_ring
nearest_neighbors_range
tsp_nearest
tsp_2opt
cluster_dbscan
clustered[]
spatial_join_nearest
spatial_join_within
spatial_join_knearest
HashMap[String]
HashMap[Int]
bulk_insert
morans_i_knn
find_neighbors
find_sorted_by_distance
find_nearest_pairs
find_nearby
compute_bbox
voronoi
voronoi_neighbors
Benchmark 实测(随机中国地址,单位:us。使用 bulk_insert 批量构建):
运行命令:moon run cmd benchmark [N](默认 N=1000)
moon run cmd benchmark [N]
缓存策略:
Index
to_array
insert
remove
GeoDB
R-tree 索引:
find_nearest
moonbitGEODB/ ├── lib/ │ ├── types/ # 核心类型定义 (GeoPoint, Address, GeoEntry, BBox) │ ├── geo/ # 地理数学运算 (Haversine, Geohash, 坐标转换, 凸包, 多边形) │ ├── parser/ # 地址解析器 (多格式解析, 中文行政区划识别) │ ├── index/ # 空间索引 (网格索引, 名称索引) │ ├── persist/ # 持久化 (二进制编解码, 原子保存, 备份, FFI IO) │ ├── gen/ # 随机中国地址生成器 │ └── db/ # 主数据库 API (GeoDB) └── cmd/ # 命令行接口
GeoPoint
Address
GeoEntry
BBox
address_match.mbt
rtree.mbt
moon build
# 设置链接器路径(解决 pthread 和 libc 找不到的问题) export LIBRARY_PATH=/usr/lib64 # 强制使用 GCC 而非 tcc(推荐) export MOON_CC=gcc # 构建项目 moon build # 运行测试 moon test
moon run cmd <address> 解析并存储地址 moon run cmd search <keyword> 按名称关键词搜索 moon run cmd fuzzy <kw> [max_dist] 模糊搜索(Levenshtein 距离) moon run cmd nearby <lat> <lng> [km] 附近查找 moon run cmd within <lat> <lng> <km> 地理围栏查询 moon run cmd tag <tag> 按标签查找 moon run cmd tags 列出所有标签 moon run cmd tag-all <t1> [t2 ...] 多标签 AND 查询 moon run cmd tag-any <t1> [t2 ...] 多标签 OR 查询 moon run cmd province <province> 按省份查找 moon run cmd city <city> 按城市查找 moon run cmd district <district> 按区县查找 moon run cmd stats 地理统计 moon run cmd export [path] 导出 CSV moon run cmd to-json [path] 导出 JSON moon run cmd to-geojson [path] 导出 GeoJSON moon run cmd add-tag <id> <tag> 添加标签 moon run cmd remove-tag <id> <tag> 删除标签 moon run cmd rename <id> <name> 重命名 moon run cmd update-coords <id> <lat> <lng> 更新坐标 moon run cmd seed [n] 生成随机地址(默认 100 条) moon run cmd save <path> 保存数据库 moon run cmd load <path> 加载数据库 moon run cmd backup <path> 创建备份 moon run cmd check <path> 完整性检查 moon run cmd info <path> 查看数据库信息 moon run cmd pattern <pattern> 通配符搜索 moon run cmd distance <id1> <id2> 两点距离 moon run cmd neighbors <id> [k] k 个最近邻 moon run cmd nearest-pairs [k] k 对最近点 moon run cmd districts [province] 区县分布 moon run cmd tag-count <tag> 标签计数 moon run cmd tag-pairs 标签共现对 moon run cmd centroid <tag> 加权质心 moon run cmd import-csv <csv_str> CSV 导入 moon run cmd import-geojson <gj_str> GeoJSON 导入 moon run cmd duplicates [dist] [edit] 重复检测 moon run cmd cluster [cell_size_km] 网格聚类 moon run cmd matrix <id1> [id2 ...] 距离矩阵 moon run cmd reverse-geocode <lat> <lng> 反向地理编码 moon run cmd dbscan [eps_km] [min_points] DBSCAN 聚类(默认 50km / 3 点) moon run cmd polygon <lat1>,<lng1> <lat2>,<lng2> ... 多边形操作 moon run cmd geohash-neighbors <hash> [precision] Geohash 邻域 moon run cmd radial-density <lat> <lng> <km> <rings> 径向密度 moon run cmd to-geojson-bbox [path] 带 BBox 的 GeoJSON moon run cmd distance-histogram [bucket_size_km] 距离直方图 moon run cmd coord-histogram lat|lng [bucket_size] 坐标直方图 moon run cmd distance-summary 距离统计摘要 moon run cmd kmeans <k> [max_iter] K-Means 聚类 moon run cmd elbow [max_k] Elbow 方法选 k moon run cmd centroid-all 全局质心 + 地理中心 moon run cmd geographic-center 球面地理中心 moon run cmd bbox-query <min_lat> <max_lat> <min_lng> <max_lng> 边界框查询 moon run cmd moran-i Moran's I 空间自相关 moon run cmd sde 标准差椭圆 moon run cmd tsp <start_id> TSP 最近邻路由 moon run cmd tsp-2opt <start_id> TSP + 2-opt 优化(再省 3-10%) moon run cmd idw <lat> <lng> [power] IDW 空间插值(反距离加权) moon run cmd concave-hull <alpha> 凹包(Alpha-Shape),alpha=0 → 凸包 moon run cmd benchmark [N] 性能基准测试(默认 1000) moon run cmd demo 一键演示(K-Means + SDE + TSP + IDW + 凹包) moon run cmd moran-i-knn Moran's I(KNN 权重,比 O(n²) 快) moon run cmd voronoi Voronoi 图(泰森多边形) moon run cmd voronoi-cell <id> 单个条目的 Voronoi 多边形 moon run cmd voronoi-neighbors <id> 条目的 Voronoi 邻居 moon run cmd delaunay Delaunay 三角剖分 moon run cmd delaunay-edges Delaunay 边(唯一) moon run cmd morans-i-lat 全局 Moran's I(纬度) moon run cmd morans-i-lng 全局 Moran's I(经度) moon run cmd hotspot-lat Getis-Ord Gi* 热点/冷点(纬度) moon run cmd hotspot-lng Getis-Ord Gi* 热点/冷点(经度) moon run cmd lisa-lat 局部 Moran's I LISA(纬度) moon run cmd lisa-lng 局部 Moran's I LISA(经度) moon run cmd kriging <lat> <lng> [k] Kriging 克里金插值 moon run cmd clear 清空所有条目 moon run cmd help 显示帮助 moon run cmd addr-match <q> <c> 语义地址匹配(查询 vs 候选) moon run cmd addr-eval <path> [N] 评测地址匹配器(JSONL 语料) moon run cmd addr-feat-dump <path> 导出 25 维特征 TSV(用于 sklearn 重训) moon run cmd corpus-db [N] 从真实地址语料构建空间 DB
# 运行默认演示 moon run cmd # 解析并存储地址 moon run cmd "北京市海淀区颐和园路5号" # 搜索关键字 moon run cmd search "颐和园" # 模糊搜索(最多 2 次编辑距离) moon run cmd fuzzy "Yuan" 2 # 附近查找(5 公里内) moon run cmd nearby 39.9 116.4 5 # 地理围栏查询 moon run cmd within 39.9 116.4 10 # 多标签 AND 查询 moon run cmd tag-all "poi" "attraction" # 按省份查找 moon run cmd province "北京市" # 生成 500 条随机地址 moon run cmd seed 500 # DBSCAN 聚类(1km 半径,最少 2 点成簇) moon run cmd dbscan 1.0 2 # 多边形查询 moon run cmd polygon 0,0 0,1 1,1 1,0 # Geohash 邻域查询 moon run cmd geohash-neighbors wx4g0d 6 # 径向密度分析 moon run cmd radial-density 39.9 116.4 1.0 10 # 保存/加载数据库 moon run cmd save geo.db moon run cmd load geo.db # 完整性检查 moon run cmd check geo.db # 数据导出 moon run cmd export output.csv moon run cmd to-geojson output.json
# Exact — suffix 统一化(幢↔栋、层↔楼 自动折叠) $ moon run cmd addr-match \ "北京市海淀区中关村南大街27号中央民族大学2号楼" \ "北京市海淀区中关村南大街27号中央民族大学2栋" level: 完全匹配 score: 0.84 dice: 0.97 road: 1 num: 0.5 # Exact — 完整 POI + 门牌号 完全一致 $ moon run cmd addr-match \ "陕西省西安市雁塔区小寨路街道长安中路100号赛高国际" \ "陕西省西安市雁塔区小寨路街道长安中路100号赛高国际" level: 完全匹配 score: 0.75 dice: 1.00 road: 1 num: 1 # Partial — 同 POI 但楼层/房间号不同(26楼 vs 26层A) $ moon run cmd addr-match \ "汉中路180号星汉大厦26楼江苏东方燃油有限公司" \ "汉中路180号星汉大厦26层A江苏东方燃油有限公司" level: 部分匹配 score: 0.84 dice: 0.97 road: 1 num: 1 # Partial — 同道路 + 同门牌段号,但建筑不同 $ moon run cmd addr-match \ "上海市浦东新区世纪大道100号环球金融中心" \ "上海市浦东新区世纪大道88号金茂大厦" level: 部分匹配 score: 0.56 dice: 0.67 road: 1 num: 0 # Partial — 同门牌号但跨城市同名 POI(LGBM 判 Partial 而非 None, # 因为 road_b=1 + feature_recall=1.0 + admin_hit=0,属于典型"地名歧义") $ moon run cmd addr-match \ "浙江省杭州市西湖区文三路90号东部软件园" \ "江苏省南京市玄武区文三路90号东部软件园" level: 部分匹配 score: 0.65 dice: 0.43 road: 1 num: 1 # None — 完全不相关 $ moon run cmd addr-match \ "北京市朝阳区建国门外大街1号国贸中心" \ "广州市天河区天河路228号正佳广场" level: 不匹配 score: 0.00 dice: 0.00 road: 0 num: 0
# 完整评测:混淆矩阵 + 三分类 F1 $ moon run cmd addr-eval testdata/data.txt 0 === Address matcher evaluation === Records: 20000 pairs: 96423 Throughput: 18284 pairs/s Agreement: 75.90% (73187/96423) Confusion matrix (rows = gold, cols = pred): 完全匹配 部分匹配 不匹配 完全匹配 948 2902 2157 部分匹配 440 21305 10146 不匹配 253 7338 50934 # 导出 25 维特征 TSV + score + gold,供 sklearn 重训 $ moon run cmd addr-feat-dump testdata/data.txt | head -3 dice road_b feat name admin_hit road_hit ... score gold 0.296 0.5 0 0 1 0 ... 0.204 2 0.143 0.5 0 0 0 0 ... 0.125 2
// 创建内存数据库 let db = @db.GeoDB::in_memory() // 插入条目(自动解析地址字符串) let entry = db.insert_raw( "bj-yiheyuan", "颐和园", 39.9999, 116.2755, "北京市海淀区颐和园路5号" ) // 批量插入(比循环 insert 快 5-20 倍,50k 仅 ~1.1s) db.bulk_insert([entry1, entry2, entry3]) // 按 ID 查找 match db.get("bj-yiheyuan") { Some(e) => println(e.name) None => println("not found") } // 按名称查找 let results = db.find_by_name("颐和园") // 按关键字模糊搜索 let results = db.find_name_contains("海淀") // 附近查找(5 公里内) let nearby = db.find_nearby( @types.GeoPoint::make(39.9999, 116.2755), radius_km=5.0, limit=10 ) // DBSCAN 密度聚类(50km 邻域,至少 3 点成簇) let clusters = db.cluster_dbscan(50.0, 3) // Geohash 前缀查询 let results = db.find_by_geohash_prefix("wx4g0d", precision=6) // 路径距离计算 let d = db.path_distance(["id1", "id2", "id3"]) // 分页查询 let page = db.page_all(limit=10, offset=0) // 地址标准化 let ok = db.normalize_address("bj-yiheyuan") // 保存到文件 ignore(db.save_to("geo.db")) // 从文件加载 let loaded = @db.GeoDB::open("geo.db")
// Geohash 编码/解码 let gh = @geo.geohash_encode(39.9087, 116.3975, 6) let pt = @geo.geohash_decode(gh) // Geohash 邻域(3×3 网格) let neighbors = @geo.geohash_neighbors(gh) // 坐标转换(WGS84 → GCJ-02) let (gcj_lng, gcj_lat) = @geo.wgs84_to_gcj02(116.4, 39.9) // 凸包计算 let hull = @geo.convex_hull(points) // 多边形面积(km²) let area = @geo.polygon_area(polygon_points) // 点在多边形内测试 let inside = @geo.point_in_polygon(point, polygon) // 平均最近邻距离 let avg_nn = @geo.average_nn_distance(points) // Voronoi 图(泰森多边形) let cells = @geo.voronoi_diagram(points, bbox) // 单个条目的 Voronoi 多边形 let poly = db.voronoi_cell("id1") // Voronoi 邻居(共享边的条目) let neighbors = db.voronoi_neighbors("id1") // Delaunay 三角剖分(Voronoi 对偶) let tris = db.delaunay() // 返回三角形索引数组 // Delaunay 边(唯一) let edges = db.delaunay_edges() // 空间自相关:Moran's I 全局聚集度检验(纬度) let moran = db.morans_i_on_lat() // 热点分析:Getis-Ord Gi* 热点/冷点检测(经度) let hotspots = db.getis_ord(vals, k = 5, threshold = 1.96) // LISA:局部 Moran's I 聚类类型(HH/LL/HL/LH) let lisa = db.lisa(vals, k = 5, threshold = 1.96) // 重复数据检测 let groups = db.find_duplicates(max_distance_km=0.1, max_edit_dist=2) // 空间网格聚类 let clusters = db.cluster_by_grid(cell_size_km=1.0) // 距离矩阵 let matrix = db.distance_matrix(["id1", "id2", "id3"]) // 径向密度分析 let rings = db.radial_density(center, ring_width_km=1.0, num_rings=10) // 反向地理编码 match db.reverse_geocode(39.9, 116.4) { Some((entry, dist)) => println("Nearest: " + entry.name) None => println("Not found") } // 性能优化示例:高效查询(O(log n) 通过 R-tree) // 查找最近 10 个邻居(避免 O(n) 全扫描) let neighbors = db.find_neighbors(target.location, 10) // 查找半径内条目(堆维护,避免 O(m log m) 全排序) let nearby = db.find_nearby(center, 5.0, limit=20) // 查找最近点对(避免 O(n²) 全对计算) let pairs = db.find_nearest_pairs(k=5)
// 基础用法 — 直接拿 MatchResult let q = "汉中路180号星汉大厦26楼江苏东方燃油有限公司" let c = "汉中路180号星汉大厦26层A江苏东方燃油有限公司" let result = @parser.match_address(q, c) match result.level { Exact => println("完全匹配,score=" + result.score.to_string()) Partial => println("部分匹配,dice=" + result.dice.to_string()) None => println("不匹配") } // result.dice — 标准化字符串的 Dice 系数 // result.feature_recall, road_recall, num_recall — 三个手工核心指标 // 带特征导出 — 拿 MatchResult + FeatureBundle (25 维中间特征) let (result2, feats) = @parser.match_address_ex(q, c) // feats.dice, feats.road_b, feats.feature_recall, feats.admin_hit, // feats.road_hit, feats.foreign_city, feats.feat_overlap, // feats.house_missing, feats.veto, feats.main_hit ... 全部可读 // 地址文本标准化(公开 API) let norm = @parser.normalize_address_text("北京市 海淀区 颐和园路5号 ") // → "北京市海淀区颐和园路5号"(全角→半角、去标点、trim) // MatchLevel 枚举工具 Exact.rank() // 2 Partial.rank() // 1 None.rank() // 0 MatchLevel::from_label("完全匹配") // → Exact
// 生成 100 条随机中国地址 let entries = @gen.gen_batch(100) // 预填充数据库 let db = @gen.gen_db(500) // 也可以通过 CLI 生成并持久化 // moon run cmd seed 500 # 自动保存到 testdata/geo_seeded.db
数据库采用纯二进制格式存储,由以下部分组成:
+------------------+ | File Header | 魔数 ("GEO1") + 版本号 + 条目数 + 创建/更新时间戳 +------------------+ | Entry Block 0 | 条目长度 + CRC32 + 序列化数据 | Entry Block 1 | ... +------------------+ | ... | +------------------+
# 运行所有测试 moon test
测试覆盖(339 个测试):
moon run cmd demo 使用 build_sample_db() 内置 61 个真实中国地标 POI,按 13 个城市分组,天然具有城市级聚类结构,可直接验证 K-Means / DBSCAN / TSP / Moran’s I:
moon run cmd demo
build_sample_db()
每条数据都包含 id(城市前缀-地标拼音)、中文名、精确经纬度、完整中文地址(精确到省/市/区/街道/门牌号)。
无需指定簇数,DBSCAN 可自动还原城市结构(3 个噪声点为距市中心 >50km 的千岛湖、武隆天生三桥、都江堰):
$ moon run cmd dbscan 50.0 3 === DBSCAN (eps=50km, min_points=3) === Cluster #1 (3 POIs): # 武汉 Cluster #2 (11 POIs): # 北京 ... Cluster #13 (3 POIs): # 昆明 Clusters: 13 Noise: 3 # 58 + 3 = 61,全部点都有归属判定 Noise points: - hz-qiandao (千岛湖) - cq-wulong (武隆天生三桥) - cd-dujiangyan (都江堰景区)
内置随机地址生成器覆盖 347 个中国主要城市(含直辖市、省会、地级市、台湾地区、港澳特别行政区),每个城市配备真实行政区划(区/县),可生成大规模性能测试数据:
运行 moon run cmd seed 1000 可快速生成 1000 条随机中国地址用于测试。
moon run cmd seed 1000
testdata/data.txt 是一份包含 20,000 条真实中文地址查询 的标注语料库,每行 1 个 JSONL 记录,每条 query 配有 5 个人工标注的候选地址(完全匹配/部分匹配/不匹配),总共约 96k 对 query-candidate 对。用于:
testdata/data.txt
moon run cmd addr-eval testdata/data.txt 0
moon run cmd corpus-db 500
testdata/geo_corpus.db
addr-feat-dump
评测命令末尾自动输出三类典型错误样本 (gold=部分→None、gold=部分→完全、gold=不→完全) 供阈值调优参考。
手工规则 OR-of-16 无法捕捉非线性特征交互(如 road_b(0.23-0.50) + feat(≥0.30) 应判 Partial 但规则漏判)。FeatureBundle 把所有中间计算结果导出给 sklearn/LightGBM:
road_b(0.23-0.50) + feat(≥0.30)
dice
road_b
feature_recall
name_recall
admin_hit
road_hit
town_hit
context_ok
house_recall
house_conflict
veto
q_structured
c_structured
feat_overlap
weak_core_exact
fuzzy_poi_overlap
reverse_poi_overlap
road_conflict
main_hit
house_missing
foreign_city
q_roads
c_roads
q_feats
c_feats
score
特征重要性 Top 3:road_b (36%) → feature_recall (24%) → dice (12%)。这三个特征占 LightGBM 决策的 **72%**,而手工规则几乎不使用 road_b 的中间分数——这是 ML 能提升 7%+ 的核心原因。
25 维 FeatureBundle [Double/Int] │ ▼ ┌──────────────────────────────┐ │ 60 棵决策树(纯 MoonBit if-else)│ │ n_estimators=20 × 3 classes │ │ max_depth=6, min_child_samples=50 │ │ tree_idx → class: tree_idx % 3 │ └──────────────────────────────┘ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ tree0 tree1 tree2 tree3 ... tree59 │ │ │ │ │ s0+L s1+L s2+L s0+L s2+L │ │ │ │ │ └─────┴─────┴─────┴────────────┘ │ ▼ ┌──────────────────────────────┐ │ s0, s1, s2 (累加 raw score) │ │ argmax(s0, s1, s2) │ └──────────────────────────────┘ │ │ │ class0 class1 class2 │ │ │ Exact Partial None
每棵树遍历 root → leaf,leaf 保存一个 raw score(LightGBM 的 leaf value)。同一类的 20 棵树的 leaf value 累加到 s0/s1/s2,最终 argmax 决定 MatchLevel。
s0
s1
s2
关键设计:
i % 3
前三轮优化将 Agreement 从 66.98% 提升到 75.90%(+8.92%,多判对 6,553 对):
第一轮(阈值调优):加强 E1 上下文门控、E2 dice 0.15→0.35、P7 新增 house_conflict 分支、降低 P1b/P6/P7 dice 阈值。消除了 1,018 个 P→Exact 误报。Agreement → **68.37% (+1.39%)**。
第二轮(结构改进 + Tokenizer 修复):
normalize_address_text
floor_ok
codes_to_string_free
第三轮(ML 集成,最大跃升 +6.79%):
第四轮(规则引擎下线,零行为变化):LightGBM 集成落地后,手工规则的输出(exact/partial)实际已不参与最终决策。本轮删除整条手工规则链(E1–E7、P1–P9)及仅服务于规则的中间变量、辅助函数与阈值常量(standalone_dice_threshold/context_dice_threshold 等),match_address 直接输出 60 树集成结果。Agreement 维持 75.90%(73,187/96,423),339 个测试全部通过;同时适配新版 MoonBit 工具链,构建零警告。
exact
partial
standalone_dice_threshold
context_dice_threshold
match_address
Honest train/test split 对比:
Apache-2.0
基于 MoonBit 编写的地理信息数据库
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
moonbitGEODB
一个基于 MoonBit 编写的地理信息数据库,专门用于存储、解析、检索中国地址信息。
快速开始
demo命令在 61 POI 样本库上依次演示:按 ID/名称检索 → 附近查询 → K-Means 宏观分区 → DBSCAN 城市簇识别(13 簇 + 3 远郊噪声点) → 标准差椭圆 → TSP NN+2-opt(节省约 265 km)→ IDW/Kriging 插值 → 凹包 → 中文地址解析。特性
.tmp再重命名),防止数据损坏高级空间分析
find_bbox(min_lat, max_lat, min_lng, max_lng)直接调用数据导入/导出
标签与聚合
其他功能
性能优化
本版本针对查询性能进行了多项优化:
find_in_ringnearest_neighbors_rangetsp_nearesttsp_2optcluster_dbscan(正确性)clustered[]统一归属/去重,初始邻居先标记再入队spatial_join_nearestspatial_join_withinspatial_join_knearestcluster_dbscanHashMap[String]每次插值 + 单网格HashMap[Int]+ dual-grid 细(0.1°)/粗(0.5°) 自适应选择bulk_insert(insert 批量)morans_i_knnfind_neighborsfind_sorted_by_distancefind_nearest_pairsfind_nearbycompute_bboxvoronoivoronoi_neighborsBenchmark 实测(随机中国地址,单位:us。使用
bulk_insert批量构建):运行命令:
moon run cmd benchmark [N](默认 N=1000)缓存策略:
Index层:compute_bbox和to_array结果在insert/remove时失效GeoDB层:Voronoi 图结果在insert/remove时失效R-tree 索引:
find_nearest、find_neighbors、find_nearby、find_nearest_pairs)均通过 R-tree 加速模块架构
核心模块说明
GeoPoint(地理坐标点)、Address(结构化地址)、GeoEntry(数据库条目)、BBox(边界框)等核心数据类型address_match.mbt实现语义地址匹配器 — 25 维中间特征提取 + LightGBM 集成(60 棵树投票),在 96,423 对真实中文地址上 Agreement **75.90%**,可对数据库内地址做模糊语义检索rtree.mbt)提供亚线性的 k 最近邻与范围查询;基于 HashMap 的名称/标签/地址索引构建与运行
环境要求
moon build零警告零错误)构建
CLI 命令参考
CLI 使用示例
基础数据库操作
语义地址匹配(真实 CLI 输出示例)
评测 + 调试
编程 API
高级 API 使用
语义地址匹配 API
随机数据生成
持久化设计
二进制文件格式
数据库采用纯二进制格式存储,由以下部分组成:
测试
测试覆盖(339 个测试):
测试数据
1. 内置精选演示数据集(61 个真实 POI)
moon run cmd demo使用build_sample_db()内置 61 个真实中国地标 POI,按 13 个城市分组,天然具有城市级聚类结构,可直接验证 K-Means / DBSCAN / TSP / Moran’s I:每条数据都包含 id(城市前缀-地标拼音)、中文名、精确经纬度、完整中文地址(精确到省/市/区/街道/门牌号)。
无需指定簇数,DBSCAN 可自动还原城市结构(3 个噪声点为距市中心 >50km 的千岛湖、武隆天生三桥、都江堰):
2. 随机地址生成器(347 城)
内置随机地址生成器覆盖 347 个中国主要城市(含直辖市、省会、地级市、台湾地区、港澳特别行政区),每个城市配备真实行政区划(区/县),可生成大规模性能测试数据:
运行
moon run cmd seed 1000可快速生成 1000 条随机中国地址用于测试。3. 真实地址评测语料库(20k 条)
testdata/data.txt是一份包含 20,000 条真实中文地址查询 的标注语料库,每行 1 个 JSONL 记录,每条 query 配有 5 个人工标注的候选地址(完全匹配/部分匹配/不匹配),总共约 96k 对 query-candidate 对。用于:moon run cmd addr-eval testdata/data.txt 0输出混淆矩阵 + 各分类 precision/recall/F1moon run cmd corpus-db 500取前 500 条记录,自动提取城市坐标,DBSCAN 聚类持久化到testdata/geo_corpus.dbaddr-feat-dump导出 FeatureBundle 中间特征后重训 LightGBM(旧手工规则阈值已随规则链一并移除),再观察 addr-eval 效果评测命令末尾自动输出三类典型错误样本 (gold=部分→None、gold=部分→完全、gold=不→完全) 供阈值调优参考。
FeatureBundle 25 维中间特征
手工规则 OR-of-16 无法捕捉非线性特征交互(如
road_b(0.23-0.50) + feat(≥0.30)应判 Partial 但规则漏判)。FeatureBundle 把所有中间计算结果导出给 sklearn/LightGBM:diceroad_bfeature_recallname_recalladmin_hitroad_hittown_hitcontext_okhouse_recallhouse_conflictvetoq_structuredc_structuredfeat_overlapweak_core_exactfuzzy_poi_overlapreverse_poi_overlaproad_conflictmain_hithouse_missingforeign_cityq_roadsc_roadsq_featsc_featsscoreLightGBM 集成架构
每棵树遍历 root → leaf,leaf 保存一个 raw score(LightGBM 的 leaf value)。同一类的 20 棵树的 leaf value 累加到
s0/s1/s2,最终 argmax 决定 MatchLevel。关键设计:
i % 3个类。实测 Python MoonBit 逐行一致(diff=0.0)优化历程
前三轮优化将 Agreement 从 66.98% 提升到 75.90%(+8.92%,多判对 6,553 对):
第一轮(阈值调优):加强 E1 上下文门控、E2 dice 0.15→0.35、P7 新增 house_conflict 分支、降低 P1b/P6/P7 dice 阈值。消除了 1,018 个 P→Exact 误报。Agreement → **68.37% (+1.39%)**。
第二轮(结构改进 + Tokenizer 修复):
normalize_address_text新增 suffix 统一化:幢→栋、层→楼、弄→号、座→栋floor_ok严格化:query 有楼层/房间号而 candidate 没有时不再判 Exactfeat_overlap:跨 token 边界的 3+ chars core 匹配codes_to_string_free修复:跳过已消费的数字 span,不再把 “25栋2楼” 吞进 POI 长 token第三轮(ML 集成,最大跃升 +6.79%):
road_b(0.23-0.50) + feat(≥0.30)这种非线性特征交互(road_b 特征重要性 34%,手工规则几乎不使用)第四轮(规则引擎下线,零行为变化):LightGBM 集成落地后,手工规则的输出(
exact/partial)实际已不参与最终决策。本轮删除整条手工规则链(E1–E7、P1–P9)及仅服务于规则的中间变量、辅助函数与阈值常量(standalone_dice_threshold/context_dice_threshold等),match_address直接输出 60 树集成结果。Agreement 维持 75.90%(73,187/96,423),339 个测试全部通过;同时适配新版 MoonBit 工具链,构建零警告。Honest train/test split 对比:
许可证
Apache-2.0