データ修正

パターンマッチングのGSQLは挿入、更新、削除に対応しています。構文は従来のGSQL (v1) と全く同じですが、データ修正機能はまだ完全にサポートされていません。

基本的に、GSQLのデータ修正には、次の2つのレベルがあります。

  1. トップレベル。修正を宣言する文は、ほかの文に従属する必要はありません。

  2. SELECTクエリ文の中で宣言。マッチテーブルはFROM-WHERE句で定義されますが、データ修正は、マッチテーブルにある頂点とエッジの情報に対して実行されます。GSQLの仕様では、このようなSELECT内の宣言をDML-サブステートメントと呼んでいます。

  • 挿入、更新、削除は、現在、コンパイルモードのみにて機能します。(例えば、RUN QUERYの前にINSTALL QUERYを実行する必要があります。) インタプリタモードでのデータ修正機能はまだ提供されていません。

  • データ修正を含むSELECTクエリには、POST-ACCUM句を1つしか使用できません。

挿入

パターンマッチングの挿入は、トップレベルとSELECT内のレベルの両方に対応しており、従来のGSQLと同じ構文を使います。頂点とエッジの挿入が可能です。

  • トップレベルの文の場合は、 INSERT INTOを使います。

  • ACCUM句またはPOST-ACCUM句の場合は、 use the xref:3.2@gsql-ref:querying:data-modification-statements.adoc#_dml_sub_insertDML-サブステートメントのINSERT] を使います。

例1. Tiger Woodsという名前の人の頂点を作成する。次に、Viktorの大好きな2012年の投稿の作者で姓の接頭文字がSである人を求める。最後に、Viktorの大好きな作者とTiger WoodsをつなぐKNOWSエッジを挿入する。

USE GRAPH ldbc_snb

#Viktorの大好きな2012年の投稿作者の姓の接頭文字がSである人を探します
INTERPRET QUERY() SYNTAX V2 {

  R  =  SELECT t
        FROM Person:s -(LIKES>)- :msg -(HAS_CREATOR>)- Person:t
        WHERE s.firstName == "Viktor" AND s.lastName == "Akhiezer"
         AND t.lastName LIKE "S%" AND year(msg.creationDate) == 2012;

  PRINT R[R.id, R.firstName, R.lastName];
}

#結果
{
  "error": false,
  "message": "",
  "version": {
    "schema": 0,
    "edition": "enterprise",
    "api": "v2"
  },
  "results": [{"R": [
    {
      "v_id": "8796093025410",
      "attributes": {
        "R.id": 8796093025410,
        "R.firstName": "Priyanka",
        "R.lastName": "Singh"
      },
      "v_type": "Person"
    },
    {
      "v_id": "2199023260091",
      "attributes": {
        "R.id": 2199023260091,
        "R.firstName": "Janne",
        "R.lastName": "Seppala"
      },
      "v_type": "Person"
    },
    {
      "v_id": "15393162796846",
      "attributes": {
        "R.id": 15393162796846,
        "R.firstName": "Mario",
        "R.lastName": "Santos"
      },
      "v_type": "Person"
    }
  ]}]
}

# 名前がtigerというPersonのノードを作ります
# そしてこのPersonを上のVictorの大好きな作者と結び付けます
CREATE QUERY InsertEdgeAndVertex () SYNTAX v2{

  #INSERT INTO 文を使って、有名人の ノードを追加します
  INSERT INTO Person VALUES (100000000,"Tiger", "Woods", "m", _, _,_,_,_,_);

  R  =  SELECT t
        FROM Person:s -(LIKES>)- :msg -(HAS_CREATOR>)- Person:t
        WHERE s.firstName == "Viktor" AND s.lastName == "Akhiezer"
         AND t.lastName LIKE "S%" AND year(msg.creationDate) == 2012
        PER (s, t)
        ACCUM
           #「tiger」とtを結び付けるエッジをタイムスタンプ6/1/2020を付加して追加します
          INSERT INTO KNOWS VALUES(100000000, t, to_datetime("2020-06-01"));

  PRINT R [R.id, R.firstName, R.lastName];
}

INSTALL QUERY InsertEdgeAndVertex
RUN QUERY InsertEdgeAndVertex()

標準提供されている簡単なRESTエンドポイントを使って結果を検証することができます。

挿入頂点の確認

Linuxシェル
#挿入された頂点の確認
curl -X GET "http://localhost:9000/graph/ldbc_snb/vertices/Person/100000000" | jq .

#結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 1
  },
  "error": false,
  "message": "",
  "results": [
    {
      "v_id": "100000000",
      "v_type": "Person",
      "attributes": {
        "id": 100000000,
        "firstName": "Tiger",
        "lastName": "Woods",
        "gender": "m",
        "birthday": "1970-01-01 00:00:00",
        "creationDate": "1970-01-01 00:00:00",
        "locationIP": "",
        "browserUsed": "",
        "speaks": [],
        "email": []
      }
    }
  ]
}

挿入エッジの確認

Linuxファイル
#tigerのID (100,000,000) を使った挿入エッジの確認
curl -X GET "http://localhost:9000/graph/ldbc_snb/edges/Person/100000000/KNOWS" | jq .
#結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 0
  },
  "error": false,
  "message": "",
  "results": [
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "8796093025410",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-06-01 00:00:00"
      }
    },
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "2199023260091",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-06-01 00:00:00"
      }
    },
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "15393162796846",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-06-01 00:00:00"
      }
    }
  ]
}
#なお、結び付いた3人の作者は、次の例ように頂点を検索するルックアップAPIを使って検証することができます:
curl -X GET "http://localhost:9000/graph/ldbc_snb/vertices/Person/8796093025410" | jq .

更新

  • トップレベルのUPDATE文は、構文v2では現在、未対応です。

    頂点の属性は、POST-ACCUM句のみで更新が可能で、エッジの属性は、ACCUM句のみで更新が可能です。

  • SELECT内で更新を実行する場合、FROMで宣言するパターンは、_1ホップ、固定長__であることが条件になります。

例2. Viktor Akhiezerと彼の友達で姓がSで始まる人を結び付けている、すべてのKNOWSエッジの作成日を「2020-10-01」に更新する。また、Person (Tiger Woods) の頂点について、頂点の作成日と彼が使っている言語を更新する。

USE GRAPH ldbc_snb

DROP QUERY UpdateKnowsTS

CREATE QUERY UpdateKnowsTS () SYNTAX v2 {

  # 頂点tigerの属性、作成日(creationDate)と使用言語(speaks)を
  # POST-ACCUMで更新します
  R = SELECT p
      FROM Person:p
      WHERE p.firstName == "Tiger" AND p.lastName == "Woods"
      POST-ACCUM
            # シンプルベースタイプの属性の更新
            p.creationDate = to_datetime("2020-6-1"),
            # コレクションタイプの属性の更新
            p.speaks = ("english", "golf");

  #DMLサブレベルで、KNOWSエッジの属性「creationDate」をACCUMで更新します
  R  =  SELECT t
        FROM Person:s-(KNOWS:e) -:t
        WHERE s.firstName == "Tiger" and s.lastName == "Woods"
        #KNOWSエッジのタイムスタンプの更新
        ACCUM e.creationDate = to_datetime("2020-10-01");
}

INSTALL QUERY UpdateKnowsTS
RUN QUERY UpdateKnowsTS()

更新結果を検証するにはRESTコールを使います。

Tiger Woodsの作成日と彼が使う言語を確認します。

Linuxシェル
curl -X GET "http://localhost:9000/graph/ldbc_snb/vertices/Person/100000000" | jq .
#結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 0
  },
  "error": false,
  "message": "",
  "results": [
    {
      "v_id": "100000000",
      "v_type": "Person",
      "attributes": {
        "id": 100000000,
        "firstName": "Tiger",
        "lastName": "Woods",
        "gender": "m",
        "birthday": "1970-01-01 00:00:00",
        "creationDate": "2020-06-01 00:00:00",
        "locationIP": "",
        "browserUsed": "",
        "speaks": [
          "english",
          "golf"
        ],
        "email": []
      }
    }
  ]
}

ソースがtiger woodsであるKNOWSエッジを確認します。

Linuxシェル
curl -X GET "http://localhost:9000/graph/ldbc_snb/edges/Person/100000000/KNOWS" | jq .

#結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 0
  },
  "error": false,
  "message": "",
  "results": [
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "8796093025410",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-10-01 00:00:00"
      }
    },
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "2199023260091",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-10-01 00:00:00"
      }
    },
    {
      "e_type": "KNOWS",
      "directed": false,
      "from_id": "100000000",
      "from_type": "Person",
      "to_id": "15393162796846",
      "to_type": "Person",
      "attributes": {
        "creationDate": "2020-10-01 00:00:00"
      }
    }
  ]
}

削除

削除の関数、 DELETE () は、エッジと頂点の削除のために、ACCUM句とPOST-ACCUM句で使うことができます。

  • トップレベルのDELETE文は構文v2では現在、未対応です。

  • エッジの削除は、ACCUM句のみで可能です。

  • 頂点は、POST-ACCUM句で削除すると最も優れたパフォーマンスが得られます。

  • SELECT内で削除を実行する場合、FROMで宣言するパターンは、1ホップ、固定長であることが条件になります。

例3. 頂点Tiger Woodsと付随したKNOWSエッジを削除する。

USE GRAPH ldbc_snb

DROP QUERY  DeleteEdgeAndVertex

CREATE QUERY DeleteEdgeAndVertex () SYNTAX v2{

  R  =  SELECT t
        FROM Person:s -(KNOWS:e)- Person:t
        WHERE s.firstName == "Tiger" AND s.lastName == "Woods"
        ACCUM
           //エッジの削除
           DELETE(e)
        POST-ACCUM DELETE(s); //ソース頂点の削除


  PRINT  R [R.id, R.firstName, R.lastName];
}

INSTALL QUERY DeleteEdgeAndVertex
RUN QUERY DeleteEdgeAndVertex()

更新結果を検証するにはRESTコールを使います。

curl -X GET "http://localhost:9000/graph/ldbc_snb/vertices/Person/100000000" | jq .
#頂点の結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 0
  },
  "error": true,
  "message": "The input vertex id '100000000' is not a valid vertex id for vertex type = Person.",
  "code": "601"
}

curl -X GET "http://localhost:9000/graph/ldbc_snb/edges/Person/100000000/KNOWS" | jq .
#エッジの結果
{
  "version": {
    "edition": "enterprise",
    "api": "v2",
    "schema": 0
  },
  "error": true,
  "message": "The input source_vertex_id '100000000' is not a valid vertex id for vertex type = Person.",
  "code": "601"
}