地理空間探索

地理空間探索クエリーの作成。

地理空間クエリーは、地理空間情報を検出するために使用します。すべての地理空間データ型(ポイント、ラインストリング、およびポリゴン)に対し、指定した値を単純なクエリーで検索できます。より複雑な探索クエリーでは、指定したポイントの半径内または指定した地理空間ポリゴン内のポイントまたはラインストリングを検出します。
重要: すべてのポイントは、WKT形式に従い、(longitude, latitude)で指定する必要があります。

適切な結果を得るには、距離計算が重要になります。DSE Searchのインデックスは、DSE Graphの地理空間データに対して作成でき、DSE Searchでは半正矢関数の公式を使用して2つのポイント間の大円距離を判断します。ポリゴンに対してDSE Searchのインデックスを作成することはできませんが、これらのインデックスは、地理空間ポイントおよびラインストリング・クエリーのパフォーマンスの向上に重要です。DSE Searchベースの地理空間クエリーと、非インデックスベースのクエリーの違いについては、注を参照してください。

スキーマとデータ

ここでの例では、次のスキーマを使用します。
// SCHEMA
// POINT
schema.propertyKey('name').Text().create()
schema.propertyKey('point').Point().withGeoBounds().create()
schema.vertexLabel('location').properties('name','point').create()
// LINESTRING
schema.propertyKey('line').Linestring().withGeoBounds().create()
schema.vertexLabel('lineLocation').properties('name','line').create()
// POLYGON
schema.propertyKey('polygon').Polygon().withGeoBounds().create()
schema.vertexLabel('polyLocation').properties('name','polygon').create()
// MATERIALIZED VIEW INDEXES
schema.vertexLabel('location').index('byname').materialized().by('name').add()
schema.vertexLabel('lineLocation').index('byname').materialized().by('name').add()
schema.vertexLabel('polyLocation').index('byname').materialized().by('name').add()
//SEARCH INDEX - ONLY WORKS FOR POINT AND LINESTRING
schema.vertexLabel('location').index('search').search().by('point').add()
schema.vertexLabel('lineLocation').index('search').search().by('line').add()
この例では、以下のデータを使用します。
// Create a point
graph.addVertex(label,'location','name','Paris','point',Geo.point(2.352222, 48.856614))
graph.addVertex(label,'location','name','London','point',Geo.point(-0.127758,51.507351))
graph.addVertex(label,'location','name','Dublin','point',Geo.point(-6.26031, 53.349805))
graph.addVertex(label,'location','name','Aachen','point',Geo.point(6.083887, 50.775346))
graph.addVertex(label,'location','name','Tokyo','point',Geo.point(139.691706, 35.689487))

// Create a linestring
graph.addVertex(label, 'lineLocation', 'name', 'ParisLondon', 'line', "LINESTRING(2.352222 48.856614, -0.127758 51.507351)")
graph.addVertex(label, 'lineLocation', 'name', 'LondonDublin', 'line', "LINESTRING(-0.127758 51.507351, -6.26031 53.349805)")
graph.addVertex(label, 'lineLocation', 'name', 'ParisAachen', 'line', "LINESTRING(2.352222 48.856614, 6.083887 50.775346)")
graph.addVertex(label, 'lineLocation', 'name', 'AachenTokyo', 'line', "LINESTRING(6.083887 50.775346, 139.691706 35.689487)")

// Create a polygon
graph.addVertex(label, 'polyLocation','name', 'ParisLondonDublin', 'polygon',Geo.polygon(2.352222, 48.856614, -0.127758, 51.507351, -6.26031, 53.349805))
graph.addVertex(label, 'polyLocation','name', 'LondonDublinAachen', 'polygon',Geo.polygon(-0.127758, 51.507351, -6.26031, 53.349805, 6.083887, 50.775346))
graph.addVertex(label, 'polyLocation','name', 'DublinAachenTokyo', 'polygon',Geo.polygon(-6.26031, 53.349805, 6.083887, 50.775346, 139.691706, 35.689487))
データ例には次の概算距離が含まれています。
// PARIS TO LONDON: 3.08 DEGREES; 344 KM; 214 MI; 344,000 M
// PARIS TO AACHEN: 3.07 DEGREES; 343 KM; 213 MI; 343,000 M
// PARIS TO DUBLIN: 7.02 DEGREES; 781 KM; 485 MI; 781,000 M
// PARIS TO TOYKO: 86.3 DEGREES; 9713 KM; 6035 MI; 9,713,000 M

指定された情報に一致する、格納されている地理空間データの検索

指定された(longitude, latitude)にマップされているポイントに一致する、格納されているデータを検索します。
g.V().
has('location','point', Geo.point(2.352222, 48.856614)).
valueMap()
結果:
{name=[Paris], point=[POINT (2.352222 48.856614)]}
指定されたポイントにマップされているラインに一致する、格納されているデータを検索します。
 g.V().
has('lineLocation','line',Geo.lineString(2.352222, 48.856614, -0.127758, 51.507351)).
valueMap()
結果:
{line=[LINESTRING (2.352222 48.856614, -0.127758 51.507351)], name=[ParisLondon]}
指定されたポイントにマップされているポリゴンに一致する、格納されているデータを検索します。
 g.V().
has('polyLocation', 'polygon',Geo.polygon(2.352222, 48.856614, -0.127758, 51.507351, -6.26031, 53.349805)).
valueMap()
結果:
{polygon=[POLYGON ((2.352222 48.856614, -0.127758 51.507351, -6.26031 53.349805, 2.352222 48.856614))], name=[ParisLondonDublin]}

指定されたポイントを中心とした、指定された半径以内の、格納されている地理空間ポイントまたはラインストリングを検索します。

これらのクエリー、および指定された地理空間ポリゴンを使用するクエリーでは、ポイント、半径、および使用する単位を指定するGeo.inside()メソッドを使用します。

Geo.inside()メソッドで使用できる単位は複数用意されています。
DEGREES
距離の度数1度の緯度は約111.2キロメートルに相当します。一方、1度の経度は赤道からの距離に依存します。赤道では、1度の経度は111.2キロメートルに相当しますが、45度の経度では、1度の経度は78.6キロメートルになります。1度の経度における物理的な距離は緯度とともに変化しますが、ここで計算するのは度数単位の大円距離のみです。
KILOMETERS
キロメートル単位の距離。
MILES
マイル単位の距離。
METERS
メートル単位の距離。
特定の場所(センターポイント)の半径内の都市(ポイント)をすべて検索します。
g.V().
has('location', 'point', Geo.inside(Geo.point(2.352222, 48.856614), 4.2, Geo.Unit.DEGREES)).
values('name')
リスト:
==>Paris
==>London
==>Aachen
クエリーの中心をパリにして4.2度の範囲内を検索すると、3つの都市が返されます。これらは、データセットに含まれているパリ、ロンドン、およびアーヘンです。
特定の場所(センターポイント)の半径内のラインストリングをすべて検索します。
g.V().
has('lineLocation', 'line', Geo.inside(Geo.point(2.352222, 48.856614), 9713, Geo.Unit.KILOMETERS)).
values('name')
リスト:
==>ParisLondon
==>LondonDublin
==>AachenTokyo
==>ParisAachen
クエリーの中心をパリにして9713キロメートル以内を検索すると、格納されている次の4つのラインストリングが返されます。これらは、パリからロンドン、ロンドンからダブリン、アーヘンから東京、およびパリからアーヘンです。ロンドンからダブリンは、格納されているラインストリングではないことに注目してください。

指定された地理空間ポリゴン内の、格納されている地理空間ポイントまたはラインストリングの検索

JTSライブラリのJARファイルがDSE Searchに追加されている場合は、検索インデックスを使用した、ポイントに対するクエリーでポリゴンを使用できます。必ず、JARファイルを追加してからグラフ・データを挿入するようにしてください。

指定された地理空間ポリゴン内のすべての都市(ポイント)を検索します。
g.V().
has('location', 'point', Geo.inside(Geo.polygon(-6.26031, 53.349805, 6.083887, 50.775346, 139.691706, 35.689487))).
values('name')
リスト:
==>Dublin
==>Aachen
==>Tokyo
この結果は驚くべきものではありません。ポリゴンの作成に使用されている3つのポイントが、検出された3つの都市を表しているためです。
WKTツールを使用して生成された、指定された地理空間ポリゴン内のすべての都市(ポイント)を検索します。
g.V().
has('location', 'point', Geo.inside(Geo.polygon(-7.9541015625, 55.148273231753834,-9.6240234375, 51.47539580264131,1.0986328125, 50.86924482345238,0.5712890625, 53.29887631763788,-7.9541015625, 55.148273231753834))).
values('name')
リスト:
==>London
==>Dublin
使用されたポリゴンは、アイルランド共和国のほとんどとイギリスの南半分を取り囲んでおり、ポリゴン内のロンドンとダブリンを検出します。
ポリゴン内のラインストリングを検索します。
g.V().
has('lineLocation', 'line', Geo.inside(Geo.polygon(-6.26031, 53.349805, 6.083887, 50.775346, 139.691706, 35.689487))).
values('name')
リスト:
==>AachenTokyo
指定されたポリゴン内の2つのポイントはアーヘンと東京を表しているため、当然ながらアーヘンから東京のラインストリングが検出されます。

スキーマとデータ

ここでの例では、次のスキーマを使用します。
//SCHEMA
// PROPERTY KEYS
// Check for previous creation of property key with ifNotExists()
schema.propertyKey('name').Text().ifNotExists().create()
schema.propertyKey('gender').Text().ifNotExists().create()
schema.propertyKey('location').Point().withGeoBounds().ifNotExists().create()
// VERTEX LABELS
schema.vertexLabel('author').properties('name','gender').ifNotExists().create()
schema.vertexLabel('place').properties('name','location').create()
// EDGE LABELS
schema.edgeLabel('livesIn').connection('author','place').ifNotExists().create()
// VERTEX INDEXES
// Secondary
schema.vertexLabel('author').index('byName').secondary().by('name').add()
// Search
schema.vertexLabel('author').index('search').search().by('name').asString().ifNotExists().add()
schema.vertexLabel('place').index('search').search().by('location')ifNotExists().add();
この例では、以下のデータを使用します。
//VERTICES
// AUTHOR VERTICES
juliaChild = graph.addVertex(label, 'author', 'name','Julia Child', 'gender', 'F')
simoneBeck = graph.addVertex(label, 'author', 'name', 'Simone Beck', 'gender', 'F')
louisetteBertholie = graph.addVertex(label, 'author', 'name', 'Louisette Bertholie', 'gender', 'F')
patriciaSimon = graph.addVertex(label, 'author', 'name', 'Patricia Simon', 'gender', 'F')
aliceWaters = graph.addVertex(label, 'author', 'name', 'Alice Waters', 'gender', 'F')
patriciaCurtan = graph.addVertex(label, 'author', 'name', 'Patricia Curtan', 'gender', 'F')
kelsieKerr = graph.addVertex(label, 'author', 'name', 'Kelsie Kerr', 'gender', 'F')
fritzStreiff = graph.addVertex(label, 'author', 'name', 'Fritz Streiff', 'gender', 'M')
emerilLagasse = graph.addVertex(label, 'author', 'name', 'Emeril Lagasse', 'gender', 'M')
jamesBeard = graph.addVertex(label, 'author', 'name', 'James Beard', 'gender', 'M')

// PLACE VERTICES
newYork = graph.addVertex(label, 'place', 'name', 'New York', 'location', Geo.point(74.0059,40.7128));
paris = graph.addVertex(label, 'place', 'name', 'Paris', 'location', Geo.point(2.3522, 48.8566));
newOrleans = graph.addVertex(label, 'place', 'name', 'New Orleans', 'location', Geo.point(90.0715, 29.9511));
losAngeles = graph.addVertex(label, 'place', 'name', 'Los Angeles', 'location', Geo.point(118.2437, 34.0522));
london = graph.addVertex(label, 'place', 'name', 'London', 'location', Geo.point(-0.1278, 51.5074));
chicago = graph.addVertex(label, 'place', 'name', 'Chicago', 'location', Geo.point(-87.6298, 41.8781136));
tokyo = graph.addVertex(label, 'place', 'name', 'Tokyo', 'location', Geo.point(139.6917, 35.6895));

// EDGES
juliaChild.addEdge('livesIn', newYork);
simoneBeck.addEdge('livesIn', paris);
louisetteBertholie.addEdge('livesIn', london);
patriciaSimon.addEdge('livesIn', newYork);
aliceWaters.addEdge('livesIn', losAngeles);
patriciaCurtan.addEdge('livesIn', chicago);
kelsieKerr.addEdge('livesIn', tokyo);
fritzStreiff.addEdge('livesIn', tokyo);
emerilLagasse.addEdge('livesIn', newOrleans);
jamesBeard.addEdge('livesIn', london);
もちろん、このデータはCSVまたは他の形式のファイルからDSE Graph Loaderを使用して読み込むことができます。

指定された都市からの特定の距離内に住んでいる作者のソート順の検索

まず、ニューヨーク(リストされているおおよそのセンターポイント)の任意の半径(50度)内にあるすべての都市名をリストします。
g.V().
has('place', 'location', Geo.inside(Geo.point(74.0,40.5),50,Geo.Unit.DEGREES)).
values('name')
結果:
==>New York
==>Paris
==>New Orleans
==>Los Angeles
まず、ニューヨーク(おおよそのセンターポイント)の任意の半径(50度)内にあるすべての都市の都市名と、これらの都市に住んでいる作者をアルファベット順にソートしてリストします。
// Order by name, not by distance from location point given
g.V().has('place', 'location', Geo.inside(Geo.point(74.0,40.5),50,Geo.Unit.DEGREES)).
order().by('name').
as('Location').
in().as('Author').
select('Location','Author').
by('name').
by('name')
検索結果:
==>{Location=Los Angeles, Author=Alice Waters}
==>{Location=New Orleans, Author=Emeril Lagasse}
==>{Location=New York, Author=Patricia Simon}
==>{Location=New York, Author=Julia Child}
==>{Location=Paris, Author=Simone Beck}
このクエリーでは、「単純な探索」で説明されている、order()select()などの追加のメソッドを使用します。
まず、ニューヨーク(おおよそのセンターポイント)の任意の半径(50度)内にあるすべての都市の都市名と、これらの都市に住んでいる作者をセンターポイントからの距離でソートしてリストします。
// Order by distance from NYC
g.V().has('place', 'location', Geo.inside(Geo.point(74.0,40.5),50,Geo.Unit.DEGREES)).
order().by{it.value('location').getOgcGeometry().distance(Geo.point(74.0059,40.7128).getOgcGeometry())}.
as('Location').
in().as('Author').
select('Location', 'Author').
by('name').
by('name')
==>{Location=New York, Author=Patricia Simon}
==>{Location=New York, Author=Julia Child}
==>{Location=New Orleans, Author=Emeril Lagasse}
==>{Location=Los Angeles, Author=Alice Waters}
==>{Location=Paris, Author=Simone Beck}
このクエリーは、クエリーの実行を成功させるためにインポートしなければならない次の追加のメソッドを導入しています。これらはgetOgcGeometry()distance()です。ライブラリのインポートは、以下を使用して元のスクリプトで実行できます。
import com.esri.core.geometry.ogc.OGCGeometry;