不管是通过支持 GPS 的智能手机查找最近的咖啡馆,还是通过社交站点查找附近的朋友,或是查看特定城市中运输某种商品的所有货车,越来越多的人和企业都使用位置感知的搜索服务。创建位置感知搜索服务通常属于昂贵的专用解决方案的一部分,并且一般由地理空间专家完成。不过,很流行的开源搜索库 Apache Lucene 和强大的 Lucene 搜索服务器 Apache Solr 最近添加了空间位置功能。
地理位置在空间搜索中至关重要!地理位置不仅在地产中至尊为王,将其用在搜索中还能帮助位于特定位置的用户快速找到有用的信息。例如,如果您是企业名录提供商(比如一个 “黄页” 站点),当用户需要找一位水管维修员时,该站点必须返回在用户住所附近的维修员。如果您运营的是一个旅游站点,那么您必须让旅游者能够搜索到他们所在的位置附近的名胜,从而帮助他们丰富旅游行程。如果您要构建一个社交网络站点,那么最好使用位置信息来帮助用户与朋友联系。位置感知设备(比如汽车导航系统和支持 GPS 的摄像机)和大量免费地图数据的普及为构建能够为终端用户搜索高级结果的 Geographical Information Systems (GIS) 提供了各种机会。
空间信息还可以被利用到搜索领域之外,但在本文中我将主要关注如何通过 Apache Lucene 和 Apache Solr 利用空间信息来改进搜索应用程序。为什么要使用搜索引擎?并不是因为它是许多很好(甚至免费)的 GIS 工具中的必要组成部分。不过,将应用程序构建在搜索引擎的基础上能够提供几个强大的功能,这是其他传统途径无法实现的。搜索系统在合并结构化和非结构化方面非常强劲,这允许用户输入自由形式的查询,比如在搜索免费文本的描述和标题的同时根据地理位置数据限制或修改结果。例如,旅游站点可以实现这样一个特性,它让用户能够在一秒之内找到马萨诸塞州波士顿市的所有 24 小时提供服务并且配有舒适床具的四星级宾馆。有些搜索系统(比如 Apache Solr)还提供对结果集进行分类、突出显示和拼写检查的功能,从而让应用程序能够帮助用户高效地查找所需的结果。
我首先简单介绍 Lucene 的一些关键概念,深入的细节留给读者自己探索。接下来,我将介绍一些基础的地理空间搜索概念。GIS 是一个广泛的领域,本文难以对其进行详尽的描述,因此我仅关注一些查找服务、人和其他日常事项所需的基础概念。本文的末尾是关于使用 Lucene 和 Solr 索引和搜索空间信息的方法的讨论。我将通过一个真实但很简单的例子来阐述这些概念,并且使用来自 OpenStreetMap (OSM) 项目的数据。
回顾关键的 Lucene 概念
Apache Lucene 是一个基于 Java 的高性能搜索库。Apache Solr 是一个使用 Lucene 通过 HTTP 来提供搜索、分类等功能的搜索服务器。它们都使用价格适中的 Apache Software License。
从本质上看,Solr 和 Lucene 都将内容表示为文档。文档由一个或多个字段 和一个表明文档的重要性的可选增强(boost)值 组成。字段由需要索引和储存的实际内容、告诉 Lucene 如何处理该内容的元数据和表明该字段的重要性的增强值组成。由您决定以何种方式将内容表示为文档和字段,这取决于您希望怎样搜索或访问文档中的信息。在每个内容单元中,您可以使用一对一的关系,也可以使用一对多的关系。例如,我可以选择用一个包含几个字段(比如 title、keywords 和 body)的文档来表示一个 Web 页面。如果是一本书,我则选择将它的每一页表示为一个独立的文档。稍后您将看到,这一区分在为搜索编码空间数据时非常重要。可以为字段中的内容建立索引,或者原样储存供应用程序使用。如果为内容建立了索引,应用程序就可以使用它。还可以分析建立了索引的内容来生成词汇(通常称为令牌)。词汇是在搜索过程中查找和使用的基础。词汇通常是一个词,但这不是必要的。
在查询方面,Lucene 和 Solr 为表达用户查询(从基础的关键字查询到短语和通配符查询)提供丰富的功能。Lucene 和 Solr 还通过应用一个或多个对空间搜索非常重要的过滤器来提供限制空间的能力。范围查询 和范围过滤器 是限制空间的关键机制。在范围查询(或过滤器)中,用户声明需要将所有搜索到的文档限制在使用自然排序的两个值之间。例如,通常使用范围查询来查找发生在过去一年或上一个月的所有文档。在处理过程中,Lucene 必须枚举文档中的词汇以识别在范围之内的所有文档。如我在稍后展示的一样,正确地设置范围查询是提升空间搜索应用程序的查询性能的关键因素之一。
Lucene 和 Solr 还提供函数查询 的概念,它允许您使用字段的值(比如经度和纬度)作为记录机制的一部分,而不是仅仅使用组成主要的记录机制的内部数据集合。该功能在后文我演示使用 Solr 的一些基于距离的函数时用到。