【FileMaker】Shopify からデータを取得するときのポイント

ポイントとか、こんな私がいうのも烏滸がましいのですが、GraphQLでShopifyのデータ取得する際に管理画面とのマッピング、それとページネーションにえれー苦労したので、備忘録です。

今回は、顧客情報(Customer)です。

Shopify GraphQLのCustomerドキュメントは、以下を参照してください。
現在この記事を書いている時点の最新バージョンは2024/10です。
Shopify GraphQLのバージョンは年に4回更新されますので、以下のページだけでなく、最新のバージョンのページでも確認してください。

https://shopify.dev/docs/api/admin-graphql/2024-10/objects/Customer

Shopify Partnersになると、"Quickstart"というテスト用のショップを用意してくれます。
今回はこのショップを使っていきます。

# 管理画面で見る顧客情報
管理画面では、こんな感じに顧客情報が展開されています。

![スクリーンショット 2024-12-23 15.38.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/a85a17b2-8c64-837d-e20c-6dda55eb1718.png)

また、一人ひとりの顧客情報は、顧客名をクリックすると、詳細ページに行けます。
![スクリーンショット 2024-12-23 15.39.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/9d76f0d3-70a5-6cee-61ca-e4431b0d8a34.png)

詳細ページの右側にある、「お客様」という枠が、顧客情報(Customer)になります。
GraphQLでは、「直近の注文」も顧客情報のGraphQLから取得できますが、この記事では、純粋にお客さま情報を取得します。

# まずは、Postmanで

Postmanで実行してみましょう。

```
query {
customers( first: 250, query: "updated_at:>2024-01-01T00:00:00Z") {
    edges {
      node {
        id
        firstName
        lastName
        displayName
        phone
        email
        updatedAt
        defaultAddress{
            phone
            address1
            address2
            country
            city
            zip
            firstName
            lastName
            company
        }
      }
    }
  }
}
```

件数は特に指定していませんが、ここでは、2024/01/01以降に更新(登録)された顧客情報を取得しています。
全件取得したい時は、ショップを立ち上げた日を指定するといいと思います。

結果は、以下のように返ってきます。

```
{
    "data": {
        "customers": {
            "edges": [
                {
                    "node": {
                        "id": "gid://shopify/Customer/7560854569210",
                        "firstName": "Karine",
                        "lastName": "Ruby",
                        "displayName": "Karine Ruby",
                        "phone": "+16135550142",
                        "email": "karine.ruby@example.com",
                        "updatedAt": "2024-08-28T09:29:51Z",
                        "defaultAddress": null
                    }
                },
                {
                    "node": {
                        "id": "gid://shopify/Customer/7560854601978",
                        "firstName": "Russell",
                        "lastName": "Winfield",
                        "displayName": "Russell Winfield",
                        "phone": "+16135550135",
                        "email": "russel.winfield@example.com",
                        "updatedAt": "2024-08-28T09:29:51Z",
                        "defaultAddress": {
                            "phone": null,
                            "address1": "105 Victoria St",
                            "address2": null,
                            "country": "Canada",
                            "city": "Toronto",
                            "zip": "M5C1N7",
                            "firstName": "Russell",
                            "lastName": "Winfield",
                            "company": "Company Name"
                        }
                    }
                },
                {
                    "node": {
                        "id": "gid://shopify/Customer/7560854634746",
                        "firstName": "Ayumu",
                        "lastName": "Hirano",
                        "displayName": "Ayumu Hirano",
                        "phone": "+16135550127",
                        "email": "ayumu.hirano@example.com",
                        "updatedAt": "2024-08-28T09:29:51Z",
                        "defaultAddress": null
                    }
                }
            ]
        }
    },
    "extensions": {
        "cost": {
            "requestedQueryCost": 13,
            "actualQueryCost": 4,
            "throttleStatus": {
                "maximumAvailable": 2000.0,
                "currentlyAvailable": 1996,
                "restoreRate": 100.0
            }
        },
        "search": [
            {
                "path": [
                    "customers"
                ],
                "query": "updated_at:>2024-01-01T00:00:00Z",
                "parsed": {
                    "and": [
                        {
                            "field": "updated_at",
                            "range_gte": "2024-01-01T00:00:00-05:00"
                        },
                        {
                            "field": "00",
                            "match_all": "00Z"
                        }
                    ]
                },
                "warnings": [
                    {
                        "field": "00",
                        "message": "Invalid search field for this query."
                    }
                ]
            }
        ]
    }
}
```
管理画面とのマッピングは、下の図のようになります。
![スクリーンショット 2024-12-23 15.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/6a65e732-69a9-c324-d094-4a6cad5f0a54.png)

FileMakerや自社のAppに取り込んで管理するときは、displayNameよりも、firstName,lastNameに分かれている情報の方が扱いやすいので、画面に表示されている情報以外にも取り込んでおくと後々やりやすいと思います。

また、マッピングをみるとわかるように、「デフォルトの住所」は、defaultAddressというコネクションで管理されています。
配送先の住所とは違うので、注意が必要です。

# FileMakerに取り込んでみる

では、我らがFileMakerでスクリプトを組んでテーブルに顧客データを保存してみます。
[Claris Connect](https://www.claris.com/ja/connect/)でもShopifyのコネクタは用意されていますが、今回使用せず、「[url から挿入](https://help.claris.com/ja/pro-help/content/insert-from-url.html)」で取得してみます。

FileMakerでGraphQLを使うときの注意点は、以下も参考にしてみてください。

https://qiita.com/tyuma/items/2fec1d2c233ec7a06b7c


## テーブルの用意
取り込む分のフィールドを作成しました。
![スクリーンショット 2024-12-23 16.17.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/0af57e23-d6dd-dbef-a5ae-d3806967c071.png)

## レイアウトの用意
スクリプトで使用するcustomerレイアウトを用意します。
FileMakerでは、新規でテーブルを作成すると、そのテーブルのレイアウトがひとつ出来上がるので、まずはそれを使います。

## スクリプトの用意
スクリプトの流れとしては、以下のような感じに組んでいきます。
1.curlでリクエストを投げる
2.取得したJSONデータをテーブルにレコードを追加

2は、取得した分だけテーブルにレコードを登録します。

curlを投げる際のポイントとして、ページネーション(pageInfo)とカーサー(cursor)があります。
1回で取得する件数を指定した場合、顧客情報が指定件数以上あった場合は、次の顧客情報をリクエストする必要があります。
ちなみに、ShopifyにGraphQLでアクセスした時に取得できる最大件数は250件です。

### pageInfo
クエリでは、次のページがあるかどうかを取得するpageInfoを指定します。
次のページがない場合は、hasNextPageにFalseが返ってきます。
前のページを指定する場合は、hasPreviousPageでTrueがあったら前のページを取得できます。

```
    pageInfo{
        hasNextPage
        hasPreviousPage
    }
```

### cursor
cursorは、顧客情報のひとつひとつにあるので、こちらもクエリに指定します。cursorは、今見ている顧客情報がどの位置にいるか、というポインタになります。
cursorは、位置情報なので、edgesの中に指定します。

```
    edges {
      cursor
      node {
        (顧客情報)...
      }
    }
```

### スクリプト
pageInfoとcursorをクエリに組み合わせると、以下のようになります。
クエリの組み立ては、ページネーションのことを考え、Loopの中で行います。
![スクリーンショット 2024-12-23 17.35.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/975cf070-fbb1-a5ba-b4f6-81053f788172.png)

あとは、いつも通り"url から挿入"のオプションにヘッダとクエリを指定します。
![スクリーンショット 2024-12-23 17.41.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/95144177-e04e-52d8-2437-08874bc7007b.png)

"url から挿入"で返ってきたエラー情報は、必ずチェックです。

![スクリーンショット 2024-12-23 17.43.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/12a3fe1b-f43a-5229-b5d8-181f60050227.png)

問題なければ、FileMakerのテーブルにセットしましょう。
ページネーション用に、hasNextPageとcursorを取得するのをお忘れなく。
![スクリーンショット 2024-12-23 18.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/3c67593a-503f-cc72-1320-34513304754f.png)

これで、テストをしてみましょう。

## テスト
ちゃんと取得できた模様です！
![スクリーンショット 2024-12-23 18.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/8351e743-c5e7-8d6b-9aac-2dd50051880c.png)

# コツを掴めば心地いい
Shopifyに限らず、GraphQLのページネーションを覚えてしまえば、どこのGraphQLでも同じ理解で組めると思います。
Shopifyに関していうと、管理画面のどの項目がGraphQLでどう指定すれば取得できるか、をドキュメントや、Postmanで実際に取得してみて合っているかどうかを確認しながら進めるといいですよ！