文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:
1.背景
地图的基础功能之一便为搜索,而搜索又分为正向搜索和逆向搜索。所谓正向搜索即输入关键字后将匹配结果进行展示,而逆向搜索则指通过位置坐标来反向查询附近的POI。
传统方案中,我们将需要支持查询数据发布成地理编码服务,基于该服务来完成搜索。但是随着数据的不断丰富,点、线、面数据不断累积,业务相关数据不断增加,单纯的兴趣点搜索已不能完全满足需求,而类似百度的全文检索才更能满足用户的需求。
针对此情况,我们分别设计了正向和逆向的全文检索方案。
2.数据存储验证
在最初方案中,我们考虑用ES来整合所有空间数据以支持全文的快速查询,但是考虑ES的环境各项目需要预装,无疑增加了项目的实施复杂度,所以我们将目光又转移回我们各项目已普遍安装的PG上。
由于PG的geometry字段可以同时写入点、线、面,这样我们可以将所有待检索的空间数据整合至一张表中。在测试中,我们将某市的全部空间数据通过编写工具整合,一共250万条,全文正向搜索可以控制在1S以内,建立gist索引后,一千米内的逆向查询也能控制在1S内,均可以满足要求。
3.正向查询设计
观察百度的搜索,其搜索结果是进行了分类的。比如收索五一,其即会出现五一劳动节,也会出现五一大道,即其返回的结果并不是完全按照命中度大小来排列,而是类型+命中度等一些列加权后进行的结果排列。
这里我不讨论其算法的实现,仅借鉴其分类思想,如正向搜索中,如果输入一个关键字,应该在每一个分页中对各类型数据均列出一两个满足的。但是,如果我们将所有类型数据整合至一张表,因为同时既要分页,又要分类,那么对大表整体查询其性能必然会有一定影响。我们做了如下设计:
a.按照大类将数据分别拆分至对应表中,查询时,分别触发对这几张表的搜索,由于我们定义的大类目前只有四类,即四张表,虽然需要多表查询,但是性能比之前是有提升的。
b.由于每种类型,满足条件的结果个数并不会一致,分页上无法保证每页出现的各类数据一样多。这里我们采用每页内容数支持浮动的方案。比如,第一页可以做到每种类型兴趣点均有两个,但是第二页中,由于部分类型兴趣点无,这第二页中展示其他几种兴趣点数据等等,且每页兴趣点的总数无需一致(以便于后台对结果的组织)。
c.对一些类型数据优先展示,比如道路等。
d.为减少搜索时数据返回量,检索时仅返回类型和编码以及描述。当鼠标移入到POI上时,则触发二次请求以获取POI详细信息。
以下为目前全文检索实现结果:
4.逆向查询设计
谷歌地图中提供了点击地图时,弹出一个搜索框,可以搜索周边数据。借用该设计逻辑,同时为了减少数据查询次数,我们将设计规定为如下:
a.通过配置以确定是否开启逆向搜索开关,并点击该开关才最终开启逆向搜索功能。
b.每一次搜索时,默认只搜索POI数据。
c.切换分类面板时,才触发对应类型的查询。
d.定义好前端接受的数据格式,支持第三方的查询URL快速接入。
最终实现结果如下:
-----欢迎转载,但保留版权,请于明显处标明出处:
如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^