forked from neo4j-documentation/knowledge-base
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,140 additions
and
95 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
articles/add-a-neo4j-instance-to-an-embedded-ha-application.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
= Add a Neo4j instance to a running embedded HA application | ||
:slug: add-a-neo4j-instance-to-an-embedded-ha-application | ||
:author: Vivek Saran | ||
:neo4j-versions: 3.4,3.5 | ||
:tags: embedded, ha | ||
:category: cluster | ||
|
||
There are situations when we would like to use the Neo4j Browser to access an embedded HA cluster. | ||
|
||
The documented approach to accomplish that goal requires changing the embedded application code as described in the Neo4j documentation: | ||
|
||
https://neo4j.com/docs/java-reference/3.4/tutorials-java-embedded/#tutorials-java-embedded-bolt/[Accessing Neo4j embedded via the Bolt protocol] | ||
|
||
There is another approach that does not require changing application code. This second approach involves adding an additional server mode instance to the cluster. Here are the steps: | ||
|
||
- Install a new Neo4j Enterprise server mode instance (using tarball/zip or other means) with the same version of Neo4j that is operational in the embedded application. | ||
- Edit the `neo4j.conf` file and update the following parameters: | ||
[source,conf] | ||
---- | ||
dbms.mode=HA | ||
ha.server_id=20 # this is just a high number to easily identify that it is a server instance | ||
ha.slave_only=true | ||
ha.initial_hosts=<initial hosts to only include the members of the embedded HA cluster> | ||
---- | ||
|
||
We don't need to add the new server instance to `ha.initial_hosts` unless it is going to be a permanent fixture in the cluster, and will be required for the cluster to startup. We have set `ha.slave_only=true` because we want to prevent this instance from becoming the Master. | ||
It will, however, be able to accept writes. | ||
|
||
- Start Neo4j on the new instance. | ||
During startup, the new instance will connect to one of the initial hosts and request to join the cluster. Part of the startup process is to discover who else is in the cluster, including instances that may not be in the inital_hosts that joined later, and also to know if any members from the inital_hosts have failed. | ||
|
||
We now have a Neo4j instance where we can use the Neo4j Browser to communicate with the graph database as we do in a conventional server mode HA cluster. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
= Geocoding with Arcgis | ||
:slug: geocoding-with-arcgis | ||
:author: Davids Pecollet | ||
:neo4j-versions: 3.5, 4.0 | ||
:tags: cypher, configuration | ||
:category: geospatial | ||
|
||
|
||
== Prerequisites | ||
|
||
* Create/obtain an Arcgis account. | ||
* Create application within your account. The application will be assigned a 'client_id' and 'secret'. | ||
|
||
=== APOC | ||
The APOC library provides a `apoc.spatial.geocode('address')` procedure (as well as `reverseGeocode`), that supports geocoding against OpenStreetMap and Google Maps. | ||
It also supports other providers (ex: opencage) with a more explicit configuration of the API call (in neo4j.conf) : | ||
|
||
[source,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 | ||
---- | ||
|
||
with *KEY* gets replaced by the API key, and *PLACE* by the address to geocode at run time (resp. *LAT*/*LNG* by the coordinates to reverse geocode). | ||
|
||
For Arcgis, the key would be the application token, and the url would look like that (that's the public Arcgis API endpoint) : | ||
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 | ||
|
||
|
||
Unfortunately, the apoc procedures expect the json response from the provider to contain a list of "results". | ||
That is not the case for the Arcgis API endpoints : | ||
|
||
* endpoint 'findAddressCandidates' returns a list of "candidates" | ||
* the other bulk geocoding endpoint 'geocodeAddresses' returns a list of "locations" | ||
|
||
So the apoc.spatial procedures can't help here. | ||
|
||
=== Workaround using apoc.load.json | ||
|
||
The apoc.load.json procedure lets you call any HTTP/REST API and process the response directly in cypher. | ||
|
||
You can use the apoc.static procedures to read the API key and URL from neo4j.conf, similarly to what apoc.spatial.geocode does. | ||
The two following properties would be required for geocoding (this is using the public arcgis server ; replace with your own Arcgis server hostname if necessary) : | ||
|
||
[source,conf] | ||
---- | ||
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= | ||
---- | ||
|
||
Then run the following cypher query : | ||
|
||
[source,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 | ||
---- | ||
|
||
== Temporary Tokens | ||
|
||
Arcgis application token may be temporary (by default 2h). That means you may not be able to hardcode a token in your neo4j.conf. | ||
To obtain a new token, you're supposed to call the Authentication API with your application credentials. | ||
You can use `apoc.load.json` again to do that in cypher. | ||
|
||
In neo4j.conf, add the building bricks of the token API call: | ||
|
||
[source,conf] | ||
---- | ||
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 | ||
---- | ||
|
||
And run the following cypher query : | ||
|
||
[source,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' | ||
---- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.