グラフ・スキーマの作成

グラフ・データベース・スキーマの作成。

グラフ・データベースのデータ・モデルの作成は、スキーマを作成するための重要な最初のステップです。データ・モデルが指定され、グラフが作成されたら、グラフ・データベース作成の次のステップは、頂点とエッジおよびそのプロパティのスキーマを定義することです。Gremlin-Groovyは、スクリプトの作成に使用される言語です。Gremlin-GroovyはApache TinkerPopエンジンにパッケージ化されており、DataStax Studio、またはDataStax EnterpriseとともにインストールされるGremlin Console(dse gremlin-console)で使用できます。

グラフ・スキーマは、create()を使用して作成するか、add()を使用して既存のスキーマに追加することができます。

始める前に

グラフを作成します

手順

  1. 任意。以前に作成したグラフを再利用する場合は、グラフ・スキーマおよびデータを削除します
  2. 任意。Gremlin Consoleで大きなスクリプトを実行する場合は、timeout値をmaxに設定して、クライアント側がタイムアウトになるのを防ぎます。スクリプト処理を必ず完了するには、この設定を使用します。このステップをStudioで行うことはできません。
    gremlin> :remote config timeout max
  3. 任意。大きなスクリプトを実行する場合は、evaluation_timeout値をmaxに設定して、サーバー側がタイムアウトになるのを防ぎます。スクリプト処理を必ず完了するには、この設定を使用します。
    graph.schema().config().option("graph.traversal_sources.g.evaluation_timeout").set("PT10M")
    重要: 1095日(最大の整数値)以上のタイムアウト値を設定すると、グラフ・セッションの限界を超過する可能性があります。新しいセッションを開始してタイムアウトを低い値に設定することで、ハング・セッションへのアクセスを回復できます。この注意事項は、すべてのタイムアウト(evaluation_timeout,、system_evaluation_timeout、analytic_evaluation_timeout、およびrealtime_evaluation_timeout)に適用されます。
  4. 以下の例に示されているサンプル・スキーマをロードします。
    1. Studioで、コード・ブロック全体をコピーして1つのセルに貼り付けてから、セルを実行します。
    2. Gremlin Consoleで、サンプル・スキーマをコピーしてスキーマ・ファイルに貼り付けます。2つの読み込み方法を示します。
      スキーマ・ファイルの場所を指定して:loadコマンドを使用します。
      gremlin> :load /tmp/RecipeSchema.groovy
      マシン・シェルで、スキーマ・ファイルの場所を指定してcatコマンドを使用してファイルを読み込み、Gremlin Consoleに渡します。
      $ cat /tmp/RecipeSchema.groovy | dse gremlin-console
    注:各コマンドは単一セッション内でサブミットされるため、複数のセルにわたっている(Studio)か、複数の行にわたっている(Gremlin Console)場合、前の行で設定された変数がGremlin Serverによって認識されません。Recipeスキーマ内の行が別々に入力されている場合、エッジ作成コマンドでエラーが発生します。
  5. 以下のステップは、複数のセクションに分割されたスクリプト全体の詳細を示しています。
  6. 頂点とエッジのプロパティを定義します。キー名の他にプロパティのデータ型を指定します。この例で作成されるプロパティは、テキスト、整数、タイムスタンプのいずれかです。他のデータ型が利用可能です。プロパティは、グラフの選択的サブセットを取得し、格納された値を取得するために使用されます。プロパティの性質はグローバルであり、探索で使用するプロパティは、頂点ラベルとプロパティのペアによって一意に識別されます。エッジ・プロパティを更新することは不経済です。なぜならば、エッジ・プロパティを更新するためにエッジ全体とそのすべてのプロパティを削除し、再作成しなければならないからです。エッジ・プロパティは、それを使用する正当な理由がある場合にしか使用しないでください。
    // Property Keys 
    // Check for previous creation of property key with ifNotExists() 
    schema.propertyKey('name').Text().ifNotExists().create() 
    schema.propertyKey('gender').Text().create()
    schema.propertyKey('instructions').Text().create()
    schema.propertyKey('category').Text().create()
    schema.propertyKey('year').Int().create()
    schema.propertyKey('timestamp').Timestamp().create()
    schema.propertyKey('ISBN').Text().create()
    schema.propertyKey('calories').Int().create()
    schema.propertyKey('amount').Text().create()
    schema.propertyKey('stars').Int().create()
    schema.propertyKey('comment').Text().single().create() // single() is optional - default
    // Example of multiple property
    // schema.propertyKey('nickname').Text().multiple().create();
    // Example meta-property added to property: 
    // schema.propertyKey('livedIn').Text().create()
    // schema.propertyKey('country').Text().multiple().properties('livedIn').create()

    プロパティ・キーが以前に存在していたかどうかをチェックするには、ifNotExists()を使用します。プロパティ・キーを作成するには、single()またはmultiple()を指定して、単一または複数のカーディナリティを使用します。デフォルトは単一のカーディナリティです。これを指定する必要はありませんが、例に示すように明示的に記述することもできます。

    メタプロパティ、つまりプロパティのプロパティを作成するには、propertyKey()の後にproperties()を続けて使用します。メタプロパティを作成する前に、プロパティ・キーが存在している必要があります。メタプロパティをネストすることはできません。つまり、メタプロパティがメタプロパティを持つことはできません。この例では、countryはメタプロパティlivedInを持つプロパティです。このプロパティとメタプロパティは、authorがその生涯のさまざまな時期に居住したことのある国を表すために使用されます。
    {
      "name":"Julia Child",
      "gender":"F",
      [ {"country": "United States", "livedIn": "1929-1949" }, {"country": "France", "livedIn": "1949-1952" } ], 
      "authored":[{
        "book":{
          "label":"book",
          "bookTitle":"Art of French Cooking Volume One",
          "publishDate":1968
        },
        "book":{
          "label":"book",
          "bookTitle":"The French Chef Cookbook",
          "publishDate":1968,
          "ISBN": "0-394-40135-2"
        }     
      }],
      "created": [{
        
          "type" : "recipe",
          "recipeTitle" : "BeefBourguignon",
          "instructions" : "Braise the beef.",
          "createDate":1967
        },
        { 
          "type" : "recipe",
          "recipeTitle" : "Salade Nicoise",
          "instructions" : "Break the lettuce into pieces.",
          "createDate": 1970
        }
      ]
    }
  7. 頂点ラベルを定義します。頂点ラベルは、作成可能な頂点のタイプを識別します。
    // Vertex Labels
    schema.vertexLabel('author').ifNotExists().create()
    schema.vertexLabel('recipe').create()
    // Example of creating vertex label with properties
    // schema.vertexLabel('recipe').properties('name','instructions').create()
    schema.vertexLabel('ingredient').create()
    schema.vertexLabel('book').create()
    schema.vertexLabel('meal').create()
    schema.vertexLabel('reviewer').create()
    // Example of custom vertex id:
    // schema.propertyKey('city_id').Int().create()
    // schema.propertyKey('sensor_id').Uuid().create()
    // schema().vertexLabel('FridgeSensor').partitionKey('city_id').clusteringKey('sensor_id').create()
    頂点ラベルが以前に存在していたかどうかをチェックするには、ifNotExists()を使用します。頂点ラベルはプロパティとともに作成できます。頂点ラベルを作成するには、自動生成される頂点IDではなくユーザー定義の頂点IDを使用します。
    注: DSE 6.0では、自動生成される頂点IDは廃止されました。

    DSE Graphでは、グラフごとに入力できる頂点ラベル数は200までです。

  8. エッジ・ラベルを定義します。エッジ・ラベルは、作成可能なエッジのタイプを識別します。
    // Edge Labels
    schema.edgeLabel('authored').ifNotExists().create()
    schema.edgeLabel('created').create()
    schema.edgeLabel('includes').create()
    schema.edgeLabel('includedIn').create()
    schema.edgeLabel('rated').properties('rating').connection('reviewer','recipe').create()

    エッジ・ラベルが以前に存在していたかどうかをチェックするには、ifNotExists()を使用します。エッジ・ラベルを作成するには、connection()で識別される隣接頂点ラベルを使用します。エッジ・ラベルは、特定のエッジのプロパティをproperties()で識別できます。

  9. クエリー処理を高速化できるインデックスを定義します。ここでは、インデックスのすべての型を示します。インデックス作成についての詳細な情報を示します。
    // Vertex Indexes
    // Secondary
    schema.vertexLabel('author').index('byName').secondary().by('name').add()
    // Materialized	  		
    schema.vertexLabel('recipe').index('byRecipe').materialized().by('name').add()
    schema.vertexLabel('meal').index('byMeal').materialized().by('name').add()
    schema.vertexLabel('ingredient').index('byIngredient').materialized().by('name').add()
    schema.vertexLabel('reviewer').index('byReviewer').materialized().by('name').add()
    // Search
    // schema.vertexLabel('recipe').index('search').search().by('instructions').asText().add()
    // schema.vertexLabel('recipe').index('search').search().by('instructions').asString().add()
    // If more than one property key is search indexed
    // schema.vertexLabel('recipe').index('search').search().by('instructions').asText().by('category').asString().add()
    
    // Edge Index
    schema.vertexLabel('reviewer').index('ratedByStars').outE('rated').by('stars').add()
    
    // Example of property index using meta-property 'livedIn': 
    // schema.vertexLabel('author').index('byLocation').property('country').by('livedIn').add()

    これらのインデックスは、食品の例のスキーマでデータの読み込みを効率化するために追加されます。

    注: create()add()の違いはわずかですが、重要です。実体(頂点ラベルまたはエッジ・ラベル)が作成され、すでに存在している場合に、インデックスまたはプロパティ・キーがその実体に関連付けられているときは、add()コマンドが使用されます。たとえば、頂点ラベルとプロパティ・キーを作成してから、プロパティ・キーが頂点ラベルに追加される場合があります。
  10. グラフ・スキーマを作成した後、確認のためにそのスキーマを検証します。この図は出力の一部を示しています。
     schema.describe()

// RECIPE SCHEMA

// To run in Studio, copy and paste all lines to a cell and run.

// To run in Gremlin console, use the next two lines:
// script = new File('/tmp/RecipeSchema.groovy').text; []
// :> @script
    	
// Property Keys 
// Check for previous creation of property key with ifNotExists() 
schema.propertyKey('name').Text().ifNotExists().create() 
schema.propertyKey('gender').Text().create()
schema.propertyKey('instructions').Text().create()
schema.propertyKey('category').Text().create()
schema.propertyKey('year').Int().create()
schema.propertyKey('timestamp').Timestamp().create()
schema.propertyKey('ISBN').Text().create()
schema.propertyKey('calories').Int().create()
schema.propertyKey('amount').Text().create()
schema.propertyKey('stars').Int().create()
schema.propertyKey('comment').Text().single().create() // single() is optional - default
// Example of multiple property
// schema.propertyKey('nickname').Text().multiple().create();
// Example meta-property added to property: 
// schema.propertyKey('livedIn').Text().create()
// schema.propertyKey('country').Text().properties('livedIn').create()
    		
// Vertex Labels
schema.vertexLabel('author').ifNotExists().create()
schema.vertexLabel('recipe').create()
// Example of creating vertex label with properties
// schema.vertexLabel('recipe').properties('name','instructions').create()
schema.vertexLabel('ingredient').create()
schema.vertexLabel('book').create()
schema.vertexLabel('meal').create()
schema.vertexLabel('reviewer').create()
// Example of custom vertex id:
// schema.propertyKey('city_id').Int().create()
// schema.propertyKey('sensor_id').Uuid().create()
// schema().vertexLabel('FridgeSensor').partitionKey('city_id').clusteringKey('sensor_id').create()
                
// Edge Labels
schema.edgeLabel('authored').ifNotExists().create()
schema.edgeLabel('created').create()
schema.edgeLabel('includes').create()
schema.edgeLabel('includedIn').create()
schema.edgeLabel('rated').properties('stars').connection('reviewer','recipe').create()
                
// Vertex Indexes
// Secondary
schema.vertexLabel('author').index('byName').secondary().by('name').add()
// Materialized	  		
schema.vertexLabel('recipe').index('byRecipe').materialized().by('name').add()
schema.vertexLabel('meal').index('byMeal').materialized().by('name').add()
schema.vertexLabel('ingredient').index('byIngredient').materialized().by('name').add()
schema.vertexLabel('reviewer').index('byReviewer').materialized().by('name').add()
// Search
// schema.vertexLabel('recipe').index('search').search().by('instructions').asText().add()
// schema.vertexLabel('recipe').index('search').search().by('instructions').asString().add()
// If more than one property key is search indexed
// schema.vertexLabel('recipe').index('search').search().by('instructions').asText().by('category').asString().add()

// Edge Index
schema.vertexLabel('reviewer').index('ratedByStars').outE('rated').by('stars').add()

// Example of property index using meta-property 'livedIn': 
// schema().vertexLabel('author').index('byLocation').property('country').by('livedIn').add()

// Schema description
// Use to check that the schema is built as desired
schema.describe()