【Shopify】GraphQL で全商品のデータを一括取得する

  • Shopify

Shopify の GraphQL API にあるProductsクエリを使えば、商品データを複数取得することが出来ます。しかし、このクエリはfirst: 10のように「最初から10個までを取得する」といった数の指定が必須です。

ページのカウント数から残りの取得数を割り出すこともできますが、Shopify ではbulkOperationなるものを使うと、一度のリクエストで全データをまとめて取得できます。

https://shopify.dev/tutorials/perform-bulk-operations-with-admin-api

Product に限らず好きな query を実行できますが、ここでは Product のデータをまとめて取得しようと思います。

クエリの確認は Insomnia や Postman などのリクエストアプリを使うとやりやすいです。

取得の流れ

最初に貼ったURLを参考にすれば動きますが、流れとしては

  1. bulkOperationRunQueryの mutation を実行(引数に取得のためのqueryを書く)
  2. クエリが実行され、実行中のクエリidが返ってくる
  3. currentBulkOperationクエリを投げ、statusCOMPLETEDになるまで一定の間隔で投げ続ける
  4. urlにクエリの結果がjsonl形式で出力されているのでダウンロードする

になります。簡単に説明すると

取得したいデータがあるので、shopifyにクエリの実行をお願いする

shopify が頑張る

「終わった?」という確認を(3)で終わるまで続ける

終わったらダウンロードURLが発行されるので、アクセスする

と、少し手間のかかる作業が必要になります。

bulkOperationRunQuery でクエリを実行してもらう

まずは普通にクエリを書きます。

例:product_statusactiveの商品情報を全件取得

本来、引数にfirstendが必須ですが不要です。

productVariants(query: "product_status:active") {
  edges {
    node {
      product {
        id
        title
      }
      price
      inventoryQuantity
    }
  }
}

ではこのクエリを、mutationに組み込みます。queryの引数に先ほどのクエリを入れるのですが、ダブルクォーテーション三つで囲む必要があるようです。さらにその直下は{}でラップします。

mutation {
  bulkOperationRunQuery (
    query: """
    	{
        productVariants(query: "product_status:active") {
          edges {
            node {
              product {
                id
                title
              }
              price
              inventoryQuantity
            }
          }
        }
      }
    """
  ) {
    bulkOperation {
      id
      status
    }
    userErrors {
      field
      message
    }
  }
}

(なんでダブルクォーテーション3つが必要なのかよく分かりません…)

ちなみに variables に引数を設定しようと思ったんですが、このダブルクォーテーションのせいなのか上手くいかなかったので、直接埋め込んでいます。variables は json 形式なので、一行ずつダブルクォーテーションで囲めばいけるのかもしれませんが、それだと結局見にくいのであまり意味はなさそう。

特にエラーなどが無ければ成功です。

currentBulkOperation で実行ステータスを確認する

これでクエリを実行してもらいましたが、終わったかどうかはこちらから逐一確認しないと教えてくれません。時間を置いてクエリを投げてみます。

(データが多い場合はすぐに確認しても実行中である可能性が高いです)

query {
  currentBulkOperation {
    id
    status
    errorCode
    createdAt
    completedAt
    objectCount
    fileSize
    url
    partialDataUrl
  }
}

statusCOMPLETEDになるまで確認し続けます。何かしらのプログラムでたたいているなら、適当な時間を設定して自動でクエリを投げるとよいかもしれません。結果を単にダウンロードして保存したいだけなら、時間を置いて投げてみてください。

ちなみに、currentBulkOperation は最新の bulkOperation の結果を表示しますが、複数の bulkOperation を同時に実行することもできるため混在することもあります。特定の実行ステータスを確認したい時は、idを指定すればよいみたいです。

{
  node(id: "bulkOperationRunQueryのID") {
    ... on BulkOperation {
      id
      status
      url
    }
  }
}

ファイルをダウンロードする

終わると、urlに長ったらしいURLが入っているのでアクセスすると自動的にファイルがダウンロードされます。

node.js などでファイルを直接読みこむ場合は、fetchなどを使ってファイルを読み込んでから解析する必要がありますが、それはまたいずれ書きます。