Cartesian空間探索

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

Cartesian空間クエリーは、Cartesian(グラフ化可能)情報を発見するために使用します。すべてのCartesianデータ型(ポイント、ラインストリング、およびポリゴン)に対し、指定した値を単純なクエリーで検索できます。より複雑な探索クエリーでは、指定したポイントの半径内または指定した空間ポリゴン内のポイントまたはラインストリングを検出します。

DSE Searchインデックスを作成すると応答時間のレイテンシーを短縮できますが、これは必須ではありません。pointおよびlinestringプロパティの検索インデックスを使用するためのスキーマは、Cartesianスキーマで作成します。

スキーマとデータ

ここでの例では、次のスキーマを使用します。
// SCHEMA
// POINT
schema.propertyKey('name').Text().create()
schema.propertyKey('point').Point().withBounds(-3, -3, 3, 3).create()
schema.vertexLabel('location').properties('name','point').create()
// LINESTRING
schema.propertyKey('line').Linestring().withBounds(-3, -3, 3, 3).create()
schema.vertexLabel('lineLocation').properties('name','line').create()
// POLYGON
schema.propertyKey('polygon').Polygon().withBounds(-3, -3, 3, 3).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','p0','point',Geo.point(0.5,0.5))
graph.addVertex(label,'location','name','p1','point',Geo.point(1,1))
graph.addVertex(label,'location','name','p2','point',Geo.point(-1,1))
graph.addVertex(label,'location','name','p3','point',Geo.point(-2,-2))
graph.addVertex(label,'location','name','p4','point',Geo.point(2,2))

// Create a linestring
graph.addVertex(label, 'lineLocation', 'name', 'l1', 'line', "LINESTRING(0 0, 1 1)")
graph.addVertex(label, 'lineLocation', 'name', 'l2', 'line', "LINESTRING(0 0, -1 1)")
graph.addVertex(label, 'lineLocation', 'name', 'l3', 'line', "LINESTRING(0 0, -2 -2)")
graph.addVertex(label, 'lineLocation', 'name', 'l4', 'line', "LINESTRING(0 0, 2 -2)")

// Create a polygon
graph.addVertex(label, 'polyLocation','name', 'g1', 'polygon',Geo.polygon(0,0,1,1,0,1,0,0))
graph.addVertex(label, 'polyLocation','name', 'g2', 'polygon',Geo.polygon(0,0,0,1,-1,1,0,0))
graph.addVertex(label, 'polyLocation','name', 'g3', 'polygon',Geo.polygon(0,0,-2,0,-2,-2,0,0))
graph.addVertex(label, 'polyLocation','name', 'g4', 'polygon',Geo.polygon(0,0,2,0,2,-2,0,0))

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

指定された(x, y)にマップされているポイントに一致する、格納されているデータを検索します。
g.V().
has('location','point', Geo.point(0.5, 0.5)).
valueMap()
結果:
{name=[p0], point=[POINT (0.5 0.5)]}
指定されたポイントにマップされているラインに一致する、格納されているデータを検索します。
 g.V().
has('lineLocation','line',Geo.lineString(0, 0, 1, 1)).
valueMap()
結果:
{line=[LINESTRING (0 0, 1 1)], name=[l1]}
指定されたポイントにマップされているポリゴンに一致する、格納されているデータを検索します。
 g.V().
has('polyLocation', 'polygon',Geo.polygon(0,0,1,1,0,1,0,0)).
valueMap()
結果:
{polygon=[POLYGON ((0 0, 1 1, 0 1, 0 0))], name=[g1]}

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

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

特定のポイント(センターポイント)の半径内のポイントをすべて検索します。
g.V().
has('location', 'point', Geo.inside(Geo.point(0, 0), 1)).
values('name')
リスト:
==>p0
クエリーの中心を(0, 0)にして1ユニット内を検索すると、データセットから1ポイントp0が返されます。
特定の場所(センターポイント)の半径内のラインストリングをすべて検索します。
 g.V().has('lineLocation', 'line', Geo.inside(Geo.point(0.0, 0.0), 1.415)).valueMap()
リスト:
==>{line=[LINESTRING (0 0, 1 1)], name=[l1]}
==>{line=[LINESTRING (0 0, -1 1)], name=[l2]}
クエリーのセンターを(0, 0)にして1.415ユニット内を検索すると、格納されている次の2つのラインストリングが返されます:l1およびl2。

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

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

指定されたCartesian空間ポリゴン内のすべてのポイントを検索します。
g.V().
has('location', 'point', Geo.inside(Geo.polygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0))).
values('name')
リスト:
==>p0
ポリゴン内のラインストリングを検索します。
g.V().
has('lineLocation', 'line', Geo.inside(Geo.polygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0))).
values('name')
リスト:
==>l1

スキーマとデータ

ここでの例では、次のスキーマを使用します。
///SCHEMA
// PROPERTY KEYS
// Check for previous creation of property key with ifNotExists()
schema.propertyKey('name').Text().ifNotExists().create()
schema.propertyKey('address').Text().ifNotExists().create()
schema.propertyKey('location').Point().withBounds(-100,-100,100,100).ifNotExists().create()
// VERTEX LABELS
schema.vertexLabel('person').properties('name').ifNotExists().create()
schema.vertexLabel('home').properties('address','location').ifNotExists().create()
schema.vertexLabel('store').properties('name','location').ifNotExists().create()
schema.vertexLabel('ingredient').properties('name').ifNotExists().create()
// EEDGE LABELS
schema.edgeLabel('livesIn').connection('person','home').ifNotExists().create()
schema.edgeLabel('isStockedWith').connection('store','ingredient').multiple().ifNotExists().create()

// SEARCH INDEXES
schema.vertexLabel('person').index('search').search().by('name').asString().ifNotExists().add()
schema.vertexLabel('home').index('search').search().by('name').by('location').add();
schema.vertexLabel('store').index('search').search().by('name').by('location').add();
schema.vertexLabel('ingredient').index('search').search().by('name').add();

この例では、以下のデータを使用します。
//VERTICES
// PERSON VERTICES
pam = graph.addVertex(label, 'person', 'name','Pam')
les = graph.addVertex(label, 'person', 'name','Les')
paul = graph.addVertex(label, 'person', 'name','Paul')
victoria = graph.addVertex(label, 'person', 'name','Victoria')
terri = graph.addVertex(label, 'person', 'name','Terri')

// HOME VERTICES
home1 = graph.addVertex(label, 'home', 'address', '555 4th St',  'location', Geo.point(7,2));
home2 = graph.addVertex(label, 'home', 'address', '1700 Coyote Rd',  'location', Geo.point(-2,1));
home3 = graph.addVertex(label, 'home', 'address', '99 Mountain Pass Hwy',  'location', Geo.point(0,0));

// STORE VERTICES
store1 = graph.addVertex(label, 'store', 'name', 'ZippyMart',  'location', Geo.point(1,5));
store2 = graph.addVertex(label, 'store', 'name', 'Quik Station',  'location', Geo.point(7,-1));
store3 = graph.addVertex(label, 'store', 'name', 'Mamma's Grocery',  'location', Geo.point(-3,-3));

// INGREDIENT VERTICES
celery = graph.addVertex(label, 'ingredient','name', 'celery');
milk = graph.addVertex(label, 'ingredient','name', 'milk');
bokChoy = graph.addVertex(label, 'ingredient','name', 'bok choy');
steak = graph.addVertex(label, 'ingredient','name', 'steak');
carrots = graph.addVertex(label, 'ingredient','name', 'carrots');
porkChops = graph.addVertex(label, 'ingredient','name', 'pork chops');

// PERSON - HOME EDGES
pam.addEdge('livesIn', home1);
les.addEdge('livesIn', home1);
paul.addEdge('livesIn',home3);
victoria.addEdge('livesIn',home3);
terri.addEdge('livesIn',home2);

// STORE - INGREDIENT EDGES
store1.addEdge('isStockedWith', milk);
store1.addEdge('isStockedWith', bokChoy);
store1.addEdge('isStockedWith', steak);
store2.addEdge('isStockedWith', steak);
store2.addEdge('isStockedWith', carrots);
store2.addEdge('isStockedWith', porkChops);
store3.addEdge('isStockedWith', milk);
store3.addEdge('isStockedWith', carrots);
store3.addEdge('isStockedWith', celery);

セロリの検索

あなたは数学の教師で、生徒のために単純なCartesian問題を作成しようとしています。生徒は丸太の上の蟻と呼ばれる、セロリ、クリーム・チーズ、レーズンで作るおやつが大好きです。このため、生徒の家から一番近い、セロリを販売している店を検索するためのお手伝いをすることにしました。

ここでは生徒の1人であるポールの家を開始点として使用します。まず、ポールの家(センターポイント)の任意の半径(10ユニットの距離)内にある店をすべてリストします。
g.V().has('store', 'location', Geo.inside(Geo.point(0,0),10)).
values('name')
結果:
==>ZippyMart
==>Quik Station
==>Mamma's Grocery
この演習ではデカルト座標点間で計算されたCartesian座標と距離を使用していますが、類似の演習では地理空間データを使用できます。
次に、ポールの家の10ユニットの半径内にある、セロリを販売している店をリストします。
g.V().has('store', 'location', Geo.inside(Geo.point(0,0),10)).as('Store').
out().has('name','celery').as('Ingred').
select('Store', 'Ingred').
by('name').
by('name')
検索結果:
==>{Store=ZippyMart, Ingred=celery}
==>{Store=Quik Station, Ingred=celery}
==>{Store=Mamma's Grocery, Ingred=celery}
このクエリーでは、「単純な探索」で説明されている、as()out()select()などの一般的なメソッドを使用して検索結果を絞ります。
最後に、ポールの家の10ユニット半径内でセロリを販売している店をリストし、ポールの家からの距離順にソートします。
// List store name, location, and ingredient in order by distance from the store
g.V().has('store', 'location', Geo.inside(Geo.point(0,0),25)).as('Store').
order().by{it.value('location').getOgcGeometry().distance(Geo.point(0,0).getOgcGeometry())}.
as('Location').
out().has('name','celery').as('Ingred').
select('Store', 'Location','Ingred').
by('name').
by('location').
by('name')
==>{Store=Mamma's Grocery, Location=POINT (-3 -3), Ingred=celery}
==>{Store=ZippyMart, Location=POINT (1 5), Ingred=celery}
==>{Store=Quik Station, Location=POINT (7 -1), Ingred=celery}
このクエリーは、order()メソッドを追加して結果をソートします。これについては「単純な探索」でも説明されています。このクエリーは、クエリーの実行を成功させるためにインポートしなければならない次のメソッドも使用する必要があります。これらはgetOgcGeometry()distance()です。ライブラリのインポートは、以下を使用して元のスクリプトで実行できます。
import com.esri.core.geometry.ogc.OGCGeometry;

これでこの問題に取り組んでいる生徒には、お気に入りのおやつを作るために必要なセロリを買うために行く店がMamma's Groceryであることがわかりました。