【FileMaker】GraphQLをFileMakerで使うときに読む記事

割と散々REST APIの実装をしてきたのですが、最近は、GraphQLでAPIを実装する機会も出てきました。
今回は、GraphQLの一般的な注意点とともに、FileMakerで実装する時のポイントを残しておこうと思います。

# 何が違う？RESTとGraphQL
そんな変わんないかな、と思ったら、全く別物だった。
一般的な違いはGoogleに聞いたりChatGPTで聞くと詳しく教えてくれると思いますが、以下のような違いを事前に把握しておくといいです。
Graph理論がざっくり分かれば、理解は早いと思います。
私もGraph理論を含むページを閲覧して、あー、と理解が進みました。

参考までに以下のページを紹介です。

https://zenn.dev/nameless_sn/articles/graphql_tutorial

この記事では、ざっくりいきます。

## 1.接続先が違う
REST：GET,PUT,DELETE,POSTごとに接続先をURLの端っこに追加
GraphQL：接続先はひとつ

→接続先はひとつですが、指定するクエリで何をしたいかを指定します。

## 2.取得する項目数が違う
REST：どかっとテーブルにあるレコードの項目を全部処理の対象にする
GraphQL：指定した項目しか処理の対象にしない

→必要最低限か、必要最大限かを確認する

## 3.明細のような情報取得で取得する項目数が違う
注文情報とその明細行で考えてみてください。
REST：1つの注文情報の明細行は全て取得する
GraphQL：明細行を5件と指定したら、本当に5件しか取得しない

→過剰なら問題ないが、不足している場合は、Orderの明細がShopify管理画面と数が合わない、などになりがち

## 3.バージョンに注意
どちらもそうなのですが、頻度の問題もあるかもです。
REST：割とバージョンアップの頻度が激しくない
GraphQL：ものによっては、年4回バージョンアップする（ShopifyとかShopifyとかShopifyとか,,,）

→Shopify GraphQLのバージョンは、年に4回ほどアップデートされるので、新しいバージョンが出たからと言って、うっかり新しいバージョン先に接続すると、今まで使用していた項目がdeprecatedになっている可能性がある

## 4.必ずpostmanやサンプルを作ってクエリをテスト
これは別記事でも口を酸っぱくして言っているのですが、くどいほどサンプルを作って動作確認をしないとです。
RESTだとざっくりデータを持ってきてくれますが、GraphQLで色々条件を指定する場合、ちゃんと思ったデータが取れているかどうかの確認が必要不可欠になります。

https://qiita.com/tyuma/items/60361a193c85ea5c9a8c

## 5.タイムスタンプに注意
使用するGraphQLによっては、接続先のタイムスタンプがUTCのことがあるので、日本で運用する場合は変換が必要です。
例えば、ShopifyでUTCを指定するときは、次のような感じです。
通常の日時表示：2024/01/01 00:00:00
UTCで指定する日時表示：2024-01-01T00:00:00Z

この形式に変換するスクリプトやカスタム関数を用意しておくと便利です。


# FileMakerで実装する時のポイント

では、我らがFileMakerでGraphQLを扱うときのポイントです。

## タイムスタンプの変換
注意事項でも書きましたが、タイムスタンプのフォーマットが指定されている場合は、そのフォーマットを作る必要があります。
日本時間とUTCでは、+9時間なので、計算します。
もっとうまい方法はごろごろ転がっていると思いますので、探してみてください。

```
Let ( 
[
%timestamp = Timestamp ( GetAsDate ( $timestamps ) ; GetAsTime ( $timestamps ) - Time ( 9 ; 0 ; 0 ) ) ;
%subTimestamp =
Substitute ( %timestamp ; 
[ "/" ; "-" ] 
 );
%dateStr = GetValue ( Substitute ( %subTimestamp ; " " ; "¶" ) ; 1 );
%timeStr = GetValue ( Substitute ( %subTimestamp ; " " ; "¶" ) ; 2 );
%timeStrValues = Substitute ( %timeStr ; ":" ; "¶" );
%hh = Right ( "00" & GetValue ( %timeStrValues ; 1 ) ; 2 );
%mm = Right ( "00" & GetValue ( %timeStrValues ; 2 ) ; 2 );
%ss = Right ( "00" & GetValue ( %timeStrValues ; 3 ) ; 2 )
];

%dateStr & "T" & %hh & ":" & %mm & ":" & %ss & "Z"

)
```


## 「url から挿入」スクリプトステップに書くときのポイント
### ・JSONの形でクエリを投げる
JSON形式にするのは、最初だけです。
以下のサンプルは、[Shopify](https://shopify.dev/docs/api/admin-graphql/)から指定された日時以降に入った注文情報をGraphQLで取得します。
変数の、pageNationとcursorは、受信した結果のJSONに入っているので、次の注文（ページ）を取得するときのスタート位置になります。
また、ordersで"first:250"と指定しているのは、一回の通信で250件を最大件数として取得せよ、という指定です。

```
JSONSetElement ( "" ; "query" ; 
"query" & 
"
{
  orders(first: 250, " & 
Case ( $pageNation ; "after:  \"" & $cursor & "\"" ; " query: \"updated_at:>" & $timestamps & "\"" ) &
") {
    pageInfo{
        hasNextPage
        hasPreviousPage
    }
    edges {
    cursor 
      node {
    id 
    name 
    email 
    phone 
    lineItems(first:250) {
      edges 
        {
          node {
            id 
            title 
            quantity
            sku 
          }
        }
    }
      }
    }
  }
}
"
; JSONString )
```
"query"と"query"が並んでややこしいですが、2個目の"query"は、データ取得のことです。
更新や削除をするときは、"mutation"を指定します。
じゃぁ、どうやって更新と削除を見分けるのか？というと、"orders"のところが、"orderUpdate"、"orderDelete"のようにして、更新や削除をするレコードを指定します。

これを、cURLに指定するのですが、ポイントは以下の記事を参考にしてみください。

https://qiita.com/tyuma/items/7f0c161509f3c5c78257

URL から挿入のオプションでは、ヘッダとクエリをつけて送信します。

```
"--request POST -S" &
" --header \"Content-Type:application/json\"" &
" --header \"" & "X-Shopify-Access-Token:" & ＜ShopifyにアクセスするToken＞ & "\"" &
" --data @$jsonQuery"
```


### ・ただのテキストで送って問題なし

先のJSONSetElement文を見て通り、クエリ内容は、単なるテキストです。
"{"と"}"がいっぱいありますが、無理やりJSONの形にはしません。
これでいいんです。

### ・必ずエラー情報も取得せよ
基本的なエラー情報は、クエリにエラー情報を取得する構文入れることで取得できます。
queryの場合は、errors、mutationの場合は、userErrorsで取得できます。
以下は、userErrorsの構文の例です。

```
    userErrors {
      code
      field
      message
    }
```

究極は、この3点になります。

## データを取得した後のポイント
データは、JSONで返ってくるので、[JSON関数](https://help.claris.com/ja/pro-help/content/json-functions.html)をほどほどに理解しておきましょう。

返ってきたデータをFileMakerのテーブルにセットするのは、そんな難しくはありません。
基本的なJSONの構文を覚えておけば、OKです。

https://help.claris.com/ja/pro-help/content/json-functions.html

先に紹介したShopifyの注文情報は、次のように返ってきます。
2件、注文があったようです。

```
data
{
  "orders": {
    "edges": [
      {
        "node": {
          "id": "gid://shopify/Order/158040885",
          "name": "山田太郎",
          "phone": "0311112222",
          "lineitems": {
              "edges": [
              {
                  "node": {
                      "id": "gid://shopify/LineItem/11111111111111",
                      "title": "夏におすすめかき氷",
                      "quantity": 1,
                      "sku":"1234567890"
                    }
                }
              {
                  "node": {
                      "id": "gid://shopify/LineItem/22222222222222",
                      "title": "口の中が凍るキャンディ",
                      "quantity": 3,
                      "sku":"5234567890"
                    }
                }
            ]
         }
      },
      {
        "node": {
          "id": "gid://shopify/Order/158040889",
          "name": "山田花子",
          "phone": "0611112222",
          "lineitems": {
              "edges": [
              {
                  "node": {
                      "id": "gid://shopify/LineItem/33333333333333",
                      "title": "伸びるアイス",
                      "quantity": 2,
                      "sku":"1234597890"
                    }
                }
              {
                  "node": {
                      "id": "gid://shopify/LineItem/22222222222222",
                      "title": "口の中が凍るキャンディ",
                      "quantity": 1,
                      "sku":"5234567890"
                    }
                }
            ]
         }
      }
    ]
  }
}
```

注文数を取得するには、注文数が返ってくるわけではないので、"data.orders.edges"の数を数えます。

```
ValueCount ( JSONListKeys ( $responseData ; "data.orders.edges" ) )
```

あらかじめ注文数が分かればいいのですが、注文に関してはShopifyのGraphQLではクエリが提供されていないようです。
なぜか、顧客だけは、顧客数が返ってくるクエリがあります。
解せぬ。

```
query {
  customerSegmentMembers(first: 1, query: "") {
    totalCount
  }
}
```

# まずは構文を覚えよう
REST APIもそうですが、GraphQLも決まった書き方があるので、使用するサービスのGraphQL取説はよく読んでおきましょう。
頭に入ってくるまで、苦しかったですが、理論を覚えてしまえば、割と書けます。