サーチ・インデックスの使用

グラフ探索のサーチ・インデックスの使用。

DSE Graphでは、DSE Search機能を利用したサーチ・インデックスを使用して効率的な探索クエリーを実現できます。DSE Searchでは 変更されたApache Solrを使用してサーチ・インデックスを作成します。Graphサーチ・インデックスは、全文のトークン化検索にasText()、文字列の完全一致検索にasString()を使用して作成できます。各オプションには、グラフ探索で要求される検索のタイプによって異なる利点があります。

これらの探索クエリーは、クエリー使用前にサーチ・インデックスが作成されていない場合は、失敗に終わることに注意することが重要です。サーチ・インデックスは、データを挿入してグラフをクエリーする前のスキーマ作成時に作成してください。サーチ・インデックスは、DSE Graphに関連してDSE Searchが起動された場合にのみ作成されます。

一般的に、探索ステップには頂点ラベルが含まれ、プロパティ・キーと特定のプロパティ値が含まれることもあります。探索では、通常g.V()の後のステップが、インデックスを参照するステップです。中間のV()探索ステップを呼び出すと、インデックス付きの追加のステップを参照して、探索対象の頂点のリストを絞り込むことができます。

手順

  • インデックスの作成からの頂点ラベルrecipeのサーチ・インデックスの例を以下に示します。
    schema.vertexLabel('recipe').index('search').search().
    by('instructions').asText().
    by('name').asString().add()

    このサーチ・インデックスでは、DSE Searchを使用して、トークン化による全文インデックスとしてinstructionsをインデックス付けし、文字列としてnameをインデックス付けします。

全文を対象にtoken()メソッドを使用した検索

  • 上述のサーチ・インデックスを使用し、探索クエリーではトークン検索により手順にSauteという単語が含まれているすべてのレシピを見つけ、レシピ名をリストします。単語を指定してSearch.token()メソッドを使用します。
    g.V().has('recipe','instructions', Search.token('Saute')).values('name')
  • 上述のサーチ・インデックスを使用し、探索クエリーでトークン・プレフィックス検索により手順にSeaというプレフィックスのある単語が含まれているすべてのレシピを見つけ、レシピ名をリストします。プレフィックス(一連の英数字)を指定してSearch.tokenPrefix()メソッドを使用します。
    g.V().hasLabel('recipe').has('instructions', Search.tokenPrefix('Sea')).values('name','instructions')

    手順にSeasonという単語を含むレシピと、手順にseasoningsという単語を含む2つのレシピが返されます。Search.tokenPrefix()インデックスでは、大文字小文字は区別されません。

  • 上述のサーチ・インデックスを使用して、探索クエリーでトークン正規表現(regex)検索により、指定された正規表現を含む単語のあるすべてのレシピを見つけます。正規表現 .*sea*in.*は、手順の中で、seaの前に任意の数の任意の文字があり、その後ろにinという文字列が見つかるまで任意の数の任意の文字があり、その後ろにも任意の数の任意の文字が続く文字列seaが見つかるレシピの名前をリストします。正規表現を指定してSearch.tokenRegex()メソッドを使用します。
    g.V().hasLabel('recipe').has('instructions', Search.tokenRegex('.*sea.*in.*')).values('name','instructions')

    このクエリ—では、Roast Pork Loin(豚ロースのロースト)のレシピに含まれるSeasonという単語は、正規表現の要件を満たさないため、Oysters Rockefeller(オイスター・ロックフェラー)のレシピのみが返されます。

非トークン・メソッドを使用した文字列での検索

  • 上述のサーチ・インデックスを使用し、探索クエリーでは非トークン検索により名前にCarrot Soupという名前が含まれているすべてのレシピを見つけます。名前を指定してeq()メソッドを使用します。
    g.V().hasLabel('recipe').has('name', eq('Carrot Soup')).values('name')

    名前に一致する文字列が見つかります。neq()は、指定された文字列に一致しないすべての文字列の検索にも使用できます。

  • 上述のサーチ・インデックスを使用し、探索クエリーで非トークン検索により名前にCarrotという名前が含まれているすべてのレシピを見つけます。名前を指定してeq()メソッドを使用します。
    g.V().hasLabel('recipe').has('name', eq('Carrot')).valueMap()

    名前の一部しか指定されていないため、一致する文字列は見つかりませんでした。asString()インデックスでは、文字列が一致する必要があります。

  • 上述のサーチ・インデックスを使用し、探索クエリーで非トークン検索によって名前がRで始まるすべての著者を見つけます。文字列を指定してprefix()メソッドを使用します。
    g.V().hasLabel('recipe').has('name', Search.prefix('R')).values('name')

    サーチ・インデックスでレシピ名がasString()で指定されている場合、名前がRで始まる著者名ごとに一致する文字列が検出されます。

  • 上述のサーチ・インデックスを使用し、探索クエリーで非トークン検索によって指定の正規表現を含む名前を持つすべてのレシピを見つけます。正規表現を指定してregex()メソッドを使用します。
    g.V().hasLabel('recipe').has('name', Search.regex('.*ee.*')).values('name')

    サーチ・インデックスでレシピ名がasString()によって指定された場合、regex .*ee.*を含む著者名ごとに一致する文字列が検索され、任意数の他の文字と任意数の他の文字の間でeeを含むすべての文字列を見つけます。

単一の探索クエリーでの2つのサーチ・インデックスの使用

  • インデックスの作成」のサーチ・インデックスの例と同等の2つ目のサーチ・インデックスを、頂点ラベルauthorを対象に作成します。
    schema.vertexLabel('author').index('search').search().
    by('name').asString().
    by('nickname').ifNotExists().add()

    このサーチ・インデックスでは、DSE Searchを使用して、トークン化による全文インデックスとしてnicknameをインデックス付けし、文字列としてnameをインデックス付けします。

  • この探索クエリーは、クエリーの実行に著者のサーチ・インデックスだけではなく、レシピのサーチ・インデックスも使用できる中間探索V()を示しています。最初のインデックスでは、Search.tokenRegex()を使用して、Braiseという単語で始まるレシピ手順を探します。クエリーのこの部分は、後で使用するためにrとラベル付けしています。次に、著者のサーチ・インデックスを使って、Jという文字で始まる著者名を探し、外向きの辺をたどって、クエリーの最初の部分で見つけた検索結果がwhere(eq('r'))によって見つかる頂点を探索します。
    g.V().has('recipe', 'instructions', Search.tokenRegex('Braise.*')).as('r').
    V().has('author', 'name', Search.prefix('J')).out().where(eq('r')).values('name')

    このクエリー探索は、Julia ChildによるBeef Bourguignonというレシピを見つけます。これは、サーチ・インデックスを複雑な操作に効果的に利用できる一例を示すものです。

地理空間値を使用した検索

  • 地理空間型検索は、地理空間型関係の検出に使用します。サーチ・インデックスは、そのような検索を可能にするために使用します。まず、サーチ・インデックスを作成する必要があります。
    schema.vertexLabel('FridgeSensor').index('search').search().
    by('location').ifNotExists().add()
  • 検索結果を理解するためには、サンプル・データが役立ちます。冷蔵庫のセンサーとして2つの頂点を登録します。
    graph.addVertex(label, 'FridgeSensor', 'name', 'jones1', 'city_id', 100, 'sensor_id', '60bcae02-f6e5-11e5-9ce9-5e5517507c66', 'location', Geo.point(-118.359770, 34.171221))
    graph.addVertex(label, 'FridgeSensor', 'name', 'smith1', 'city_id', 100, 'sensor_id', '61deada0-3bb2-4d6d-a606-a44d963f03b5', 'location', Geo.point(-115.655068, 35.163427))
    

    センサーに名前を与え、場所を表すデータ型Pointに加えて、市町村IDとセンサーIDを指定します。

  • Geo.inside()メソッドを使用して、中心が(-110、30)にあり、半径20ユニットの円として指定された多角形Distance内にあるという要件を満たすすべてのセンサーをクエリーによって見つけられます。
    Distance d = Geo.distance(-110,30,20)
    g.V().hasLabel('FridgeSensor').has('location', Geo.inside(d)).values('name')