Vincent's Essays

博客园 首页 新随笔 联系 订阅 管理

Memoria 开发记录 28:地点检索不能迷信 POI——行政区字段与高德解析边界

前言

相册里的地点搜索非常容易被“地图服务能搜到”误导。用户输入“青岛市”,高德 POI 搜索当然能返回结果,但返回的可能是“青岛市人民政府”,而不是行政区青岛市本身。

如果应用把所有地点都交给 POI 搜索,就会把行政区、景区、商圈、学校、建筑物混成一类。短期看召回变多,长期会让搜索边界变得不可控。

地点检索必须先区分:用户要的是行政范围,还是一个具体地点。

行政区和 POI 是两种不同语义

行政区是范围:

中国
山东省
青岛市
市南区

POI 是点或小区域:

五四广场
夫子庙
某某学校
某个酒店
某个商场

行政区适合匹配照片已经写入的 country/province/city/district/adcode 字段。POI 则需要结合 POI ID、AOI ID、地址文本、坐标中心和半径。

把行政区送去 POI search,可能会返回政府机关、火车站、酒店或其他同名地点。这不是“召回更强”,而是把查询含义改掉了。

为什么不能靠本地硬编码判断所有地点

地点名称非常复杂,不能靠少量后缀硬编码解决。比如“西海岸”可以是新区,也可以是更宽泛的区域概念;“景区”“街区”“校区”也不是行政区。为了迎合某个测试样例写规则,很容易制造另一个错误。

更稳妥的分工是:

  • LLM 负责从自然语言中区分行政区、POI、景区、校区、商圈等意图;
  • 客户端只做少量确定性修正,例如明显的“某某市”不应被当成 POI;
  • Amap 负责解析具体 POI 的中心点和行政信息;
  • 本地搜索执行最终边界。

这样避免把测试案例写进业务规则,也避免把所有判断都推给远程服务。

这次修复的一个关键点是:country/province/city/district 不再调用 Amap place/text。行政区查询直接保留原始结构,进入本地字段匹配。

青岛市:
  type = city
  aliases = 青岛市 / 青岛
  match local city/adcode/geoTextTokens

五四广场:
  type = poi
  resolve by Amap place/geocode
  use POI/AOI/center radius

这样“青岛市”不会被错误解析成“青岛市人民政府”,也不会因为高德 place/text 网络波动导致整个检索失败。

地图 API 失败不能让搜索崩掉

移动端搜索不能假设地图 API 永远稳定。实际调试中,Lambda 从 AWS 区域访问高德 place/text 可能出现 fetch 超时,而 regeo 正常。这说明不同上游接口、不同区域、不同网络路径都有失败可能。

代理层因此增加了:

  • Amap 请求短超时;
  • 简单重试;
  • IPv4 优先;
  • place/text 失败后 fallback 到 geocode/geo
  • 明确的 502 错误体;
  • 客户端日志输出状态码和响应体。

搜索系统也应该允许地点解析失败后退回本地文本匹配,而不是把用户看到的结果变成空白。

半径和兄弟 POI 的取舍

POI 搜索还有一个常见问题:照片定位可能偏移。用户在夫子庙景区拍照,系统可能定位到附近某个青年旅舍。如果地点匹配过于严格,会搜不出合理结果;如果过于宽松,又会把完全无关的兄弟 POI 混进来。

更实际的策略是:

  • 景区、校园、商圈等区域型地点使用合理半径;
  • 允许一定定位偏移;
  • 不能跨城市或几十公里错配;
  • 用语义和时间进一步约束;
  • 不为了单个 case 写特化规则。

地点检索追求的是“合理可解释”,不是地图数据库意义上的绝对精确。

总结

地点搜索的核心不是调用一次 POI API,而是先理解地点类型,再选择合适的本地或远程匹配方式。

关键经验包括:

  • 行政区和 POI 不能混成一类;
  • 行政区应优先使用本地结构化字段;
  • POI 才需要远程解析中心点、ID 和半径;
  • 远程 place search 失败不能让检索整体失败;
  • 地点半径要容忍定位偏移,但不能跨城市误匹配;
  • 不应为了个别测试样例写硬编码规则。

对应提交:eea8e41d217919ea4638a07c235e

posted on 2026-06-17 01:06  Vincentson  阅读(0)  评论(0)    收藏  举报