インデックス・スキーマの追加

インデックス・データベース・スキーマの追加

すべてのインデックス・スキーマは、以前に作成されたプロパティと頂点ラベルに基づいており、add()を使用して既存のスキーマに追加されます。

始める前に

プロパティ・キー・スキーマ頂点ラベル・スキーマを作成します

手順

マテリアライズド・インデックス
  1. グローバル・インデックスのマテリアライズド・ビュー・インデックスを作成します。
    schema.vertexLabel('person').index('byName').materialized().by('name').add()

    インデックスの頂点ラベルおよびプロパティ・キーを、vertexLabel()ステップおよびby()ステップでそれぞれ識別します。index()ステップでインデックスに名前を付けます。materialized()ステップは、インデックスをマテリアライズド・ビュー・インデックスとして識別します。

  2. エッジ・インデックスのマテリアライズド・ビューを作成します。エッジ・インデックスは、特定の頂点ラベルに対する頂点中心インデックスです。たとえば、次の例では、レビュー担当者が評価するものをインデックス作成します。
    schema.vertexLabel('person').index('ratedByStars').outE('reviewed').
      by('stars').ifNotExists().add()
    インデックスの頂点ラベルおよびプロパティ・キーを、vertexLabel()ステップおよびby()ステップでそれぞれ識別します。index()ステップでインデックスに名前を付けます。outE()ステップは、エッジの方向を定義するために使用されます。
    注: すべてのエッジ・インデックスはマテリアライズド・ビューとして作成されるため、エッジおよびプロパティのインデックスでは、materialized()手順が含まれません。
  3. 内向きエッジと外向きエッジの両方のインデックスを作成するエッジ・インデックスを作成します。
    schema.vertexLabel('person').index('ratedByStars').bothE('reviewed').
      by('stars').ifNotExists().add()

    インデックスの頂点ラベルおよびプロパティ・キーを、vertexLabel()ステップおよびby()ステップでそれぞれ識別します。index()ステップでインデックスに名前を付けます。bothE()ステップは、エッジの方向を定義するために使用されます。

  4. プロパティ・インデックスのマテリアライズド・ビューを作成します。
    schema.vertexLabel('person').index('byStartYear').
      property('country').by('startYear').add()
    vertexLabel()ステップで、インデックスの頂点ラベルを識別します。index()ステップでインデックスに名前を付けます。property()ステップはプロパティ・キーを識別し、by()ステップは、そのメタプロパティを識別します。
    注: すべてのエッジ・インデックスはマテリアライズド・ビューとして作成されるため、エッジおよびプロパティのインデックスでは、materialized()手順が含まれません。
検索インデックス
  1. 最も一般的には、検索インデックスは複数の列で作成され、1つのステートメント内で複数のby()ステップとしてチェーンされます。
    schema.vertexLabel('recipe').index('search').search().by('name').by('instructions').add()

    インデックスの頂点ラベルおよびプロパティ・キーを、vertexLabel()ステップおよびby()ステップでそれぞれ識別します。index()ステップでインデックスsearchに名前を付けます。使用できるのは、この命名規則のみです。search()ステップは、インデックスを検索インデックスとして識別します。オプションが指定されていないため、プロパティはテキストと文字列の両方としてインデックス付けされます。

    ヒント: 頂点ラベルごとに作成できる検索インデックスは1つだけです。

    トークン化(TextField)形式と非トークン化(StrField)形式の両方でテキスト検索インデックスがデフォルトで作成されます。つまり、インデックスが作成されたすべてのテキスト頂点プロパティでどのテキスト述語(token、tokenPrefix、tokenRegex、eq、neq、regex、prefix)でも使用できます。実際的には、asString()メソッドを使用して検索インデックスを作成する必要があるのは、在庫カテゴリ(食卓用金物、靴、衣服)など、トークン化とテキスト解析が絶対に役に立たない場合だけです。複数の文章から成る長い記述など、トークン化されたテキストの検索には、asText()メソッドが役に立ちます。クエリー最適化ツールは、使用されているテキスト述語に基づいて、解析済みインデックスと未解析インデックスのどちらを使用するかを選択します。

  2. 1つのプロパティ・キーのみがText()としてインデックス付けされた検索インデックスを作成します。
    schema.vertexLabel('recipe').index('search').search().by('instructions').asText().add()
  3. 検索インデックスは、テキスト・インデックス・オプションとともに文字列インデックス・オプションを指定できます。
    schema.vertexLabel('recipe').index('search').search().by('instructions').asString().by('name').asText().add()

    この例では、プロパティごとに検索インデックスがどのように構築されるかを具体的に示します。

  4. 検索インデックスでは、テキスト以外のデータ型も含めることもできます。
    schema.vertexLabel('recipe').index('search').search().by('year').by('name').asString().add()
    テキスト以外のデータ型はスキーマから推測され、DSE Searchはこれに相当するSolrデータ型を使用します。この例では、yearでは整数としてインデックスが作成されます。
    注意: Decimalデータ型ではSolrDecimalStrFieldとしてインデックスが作成されます。IntLongFloatまたはDoubleを使用して、ソート・クエリーおよび範囲クエリーにSolrデータ型が使用されていることを確認します。
  5. 地理空間データの検索インデックスを作成します。
    schema.propertyKey("coordinates").Point().single().create()
    schema.propertyKey("name").Text().single().create()
    
    schema.vertexLabel("place").properties("coordinates", "name").create()
    schema.vertexLabel("place").index("search").search().by("name").asText().by("coordinates").add()
    

    この例では、プロパティcoordinatesは経度と緯度を定義するポイントを表します。検索インデックスには、妥当なasText()またはasString()メソッドを持たないcoordinatesが含まれます。詳細については、「地理空間スキーマ」を参照してください。

  6. DSE Graphは地理空間検索をネイティブでサポートしますが、検索インデックスなしの地理空間検索は、グラフに含まれる頂点の数の増加に応じて拡張しません。検索インデックスを使用せずにこのようなクエリーを行うと、フルスキャンが必要となるため、クエリー・パフォーマンスがひどく低下します。DSE Searchインデックスは、ポイントとラインストリングのインデックスを作成できますが、ポリゴンのインデックスを作成できません。
    //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()
    空間クエリーでは、検索インデックスがなくても常に正確な結果が返されます。ところが、DSE Searchインデックスの場合は、正確さと引き換えにパフォーマンスが犠牲になることがあります。
    注: DSE Searchインデックスの有無にかかわらず、同じ地理空間クエリーが実行された場合に混乱が生じる可能性があります。地理空間クエリーでは、検索インデックスがなくても常に正確な結果が返されます。ところが、DSE Searchインデックスの場合は、maxDistErr(デフォルト:0.000009)distErrPct(デフォルト:0.025)という2つの調整可能パラメーターを使用して、クエリーの正確さと引き換えに、書き込みパフォーマンスとインデックス・サイズが犠牲になります。これらの2つの例で結果が一致していないのは、パラメーターのデフォルト値の距離計算アルゴリズムにばらつきがあるためです。DSE Graphは、検索インデックスの作成時にこれら2つのパラメーターの値を渡すことができます。withError(maxDistErr, distErrPct)maxDistErrを「0.0」に変更して、インデックス・ベース・クエリーと非インデックス・ベース・クエリーの両方で同じ値が生成されるようにします。
    schema.vertexLabel('location').index('search').search().by('point').withError(0.000009,0.0).add()
    
  7. タイムスタンプ・データの検索インデックスを作成します。
    schema. propertyKey('review_ts).Timestamp().create()
    schema.propertyKey('name').Text().create()
    schema.vertexLabel('rating').properties('name', 'review_ts').create()
    schema.vertexLabel('rating').index('search').search().by('name','review_ts').add()
セカンダリ・インデックス
  1. グローバル・インデックスをセカンダリ・インデックスとして作成します。
    schema.vertexLabel('recipe').index('byRecipe').secondary().by('name').add()

    インデックスの頂点ラベルおよびプロパティ・キーを、vertexLabel()ステップおよびby()ステップでそれぞれ識別します。index()ステップでインデックスに名前を付けます。secondary()ステップは、インデックスをセカンダリ・インデックスとして識別します。

ドキュメント全体で使用されるDSE QuickStartの例に使用されるエッジ・ラベル:
// ********
// VERTEX INDEX
// ********
// SYNTAX:
// index('index_name').
//    [secondary() | materialized() | search()].
//    by('propertykey_name').
//    [ asText() | asString() ].
//    add()
// ********

schema.vertexLabel('person').index('byName').materialized().by('name').add()
schema.vertexLabel('meal_item').index('byName').materialized().by('name').add()
schema.vertexLabel('ingredient').index('byName').materialized().by('name').add()
//schema.vertexLabel('recipe').index('byCuisine').materialized().by('cuisine').add()
//schema.vertexLabel('book').index('byName').materialized().by('name').add()

schema.vertexLabel('meal').index('byType').secondary().by('type').add()

schema.vertexLabel('recipe').index('search').search().
  by('instructions').by('name').by('cuisine').add()
schema.vertexLabel('book').index('search').search().
  by('name').by('publishYear').add()
schema.vertexLabel('location').index('search').search().
  by('geoPoint').withError(0.000009,0.0).add()
schema.vertexLabel('store').index('search').search().by('name').add()
schema.vertexLabel('home').index('search').search().by('name').add()
schema.vertexLabel('fridgeSensor').index('search').search().
  by('cityId').by('sensorId').by('name').add()

// ********
// EDGE INDEX
// ********
// SYNTAX:
// index('index_name').
//    [outE('edgeLabel') | inE('edgeLabel') ].
//    by('propertykey_name').
//    add()
// ********

schema.vertexLabel('recipe').index('byStars').inE('reviewed').
  by('stars').ifNotExists().add()
schema.vertexLabel('person').index('ratedByStars').outE('reviewed').
  by('stars').ifNotExists().add()
schema.vertexLabel('person').index('ratedByDate').outE('reviewed').
  by('year').ifNotExists().add()
schema.vertexLabel('person').index('ratedByComments').outE('reviewed').
  by('comment').ifNotExists().add()
schema.vertexLabel('recipe').index('byPersonOrRecipe').bothE('created').
  by('createDate').ifNotExists().add()

// ********
// PROPERTY INDEX using meta-property 'livedIn'
// ********
// SYNTAX:
// index('index_name').
//    property('propertykey_name').
//    by('meta-propertykey_name').
//    add()
// ********

schema.vertexLabel('person').index('byStartYear').
  property('country').by('startYear').add()
schema.vertexLabel('person').index('byEndYear').
  property('country').by('endYear').add()