知识库

使用 ArcGIS 进行地理编码

先决条件

  • 创建/获取 ArcGIS 账户。

  • 在您的账户中创建应用程序。该应用程序将被分配一个“client_id”和“secret”。

APOC

APOC 库提供了一个 apoc.spatial.geocode('address') 过程(以及 reverseGeocode),它支持针对 OpenStreetMap 和 Google Maps 进行地理编码。它还支持其他提供商(例如:opencage),并通过更明确的 API 调用配置(在 neo4j.conf 中)

apoc.spatial.geocode.provider=opencage
apoc.spatial.geocode.opencage.key=<api_key>
apoc.spatial.geocode.opencage.url=http://api.opencagedata.com/geocode/v1/json?q=PLACE&key=KEY
apoc.spatial.geocode.opencage.reverse.url=http://api.opencagedata.com/geocode/v1/json?q=LAT+LNG&key=KEY

其中 **KEY** 在运行时替换为 API 密钥,**PLACE** 替换为要进行地理编码的地址(相应的 **LAT** / **LNG** 替换为要进行反向地理编码的坐标)。

对于 ArcGIS,密钥将是应用程序令牌,URL 将如下所示(这是公共 ArcGIS API 端点):apoc.spatial.geocode.arcgis.url=https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?f=json&outFields=Match_addr,Addr_typ&singleLine=PLACE&token=KEY

不幸的是,apoc 过程期望提供程序的 json 响应包含一个“results”列表。ArcGIS API 端点并非如此

  • 端点“findAddressCandidates”返回一个“candidates”列表

  • 另一个批量地理编码端点“geocodeAddresses”返回一个“locations”列表

因此,apoc.spatial 过程在这里无济于事。

使用 apoc.load.json 的解决方法

apoc.load.json 过程允许您调用任何 HTTP/REST API 并直接在 Cypher 中处理响应。

您可以使用 apoc.static 过程从 neo4j.conf 读取 API 密钥和 URL,类似于 apoc.spatial.geocode 的操作。地理编码需要以下两个属性(这是使用公共 arcgis 服务器;如有必要,请替换为您自己的 ArcGIS 服务器主机名)

apoc.static.arcgis.key=<arcgis_token>
apoc.static.arcgis.geocode_url=https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?f=json&outFields=Match_addr,Addr_typ&singleLine=

然后运行以下 Cypher 查询

WITH 'Statue of Liberty, Liberty Island New York, NY 10004' as address
// get the configuration properties
CALL apoc.static.getAll("arcgis") yield value AS arcgis
// build the URL
WITH arcgis.geocode_url+apoc.text.urlencode(address)+'&token='+ arcgis.key as url
// extract the top result
CALL apoc.load.json(url, '$.candidates[0].location') YIELD value as location
return location.x, location.y

临时令牌

ArcGIS 应用程序令牌可能是临时的(默认情况下为 2 小时)。这意味着您可能无法在 neo4j.conf 中硬编码令牌。要获取新令牌,您应该使用应用程序凭据调用身份验证 API。您可以再次使用 apoc.load.json 在 Cypher 中执行此操作。

在 neo4j.conf 中,添加令牌 API 调用的构建块

apoc.static.arcgis.client_id=<application_client_id>
apoc.static.arcgis.client_secret=<secret>
apoc.static.arcgis.token_url=https://www.arcgis.com/sharing/rest/oauth2/token?grant_type=client_credentials

然后运行以下 Cypher 查询

CALL apoc.static.getAll("arcgis") yield value AS arcgis
WITH arcgis.token_url+'&client_id='+arcgis.client_id+'&client_secret='+arcgis.client_secret as tokenUrl
CALL apoc.load.json(tokenUrl) YIELD value as tokenResponse
WITH tokenResponse.access_token as token
// proceed with geocoding using 'token'